diff --git a/.noir-sync-commit b/.noir-sync-commit index 619e948d03f..ba95bd5998e 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -c8a25b52a484115663cccf614bbebe3ca11778f3 +ebc4d2cf2b91658a10393733407f33d50a0faaf1 diff --git a/noir/noir-repo/.github/workflows/reports.yml b/noir/noir-repo/.github/workflows/reports.yml index 625d3771277..85a54147423 100644 --- a/noir/noir-repo/.github/workflows/reports.yml +++ b/noir/noir-repo/.github/workflows/reports.yml @@ -217,10 +217,24 @@ jobs: ./memory_report.sh mv memory_report.json ../memory_report.json - - name: Upload memory report + - name: Upload compilation memory report uses: actions/upload-artifact@v4 with: - name: in_progress_memory_report + name: in_progress_compilation_mem_report + path: memory_report.json + retention-days: 3 + overwrite: true + + - name: Generate execution memory report + working-directory: ./test_programs + run: | + ./memory_report.sh 0 1 + mv memory_report.json ../memory_report.json + + - name: Upload execution memory report + uses: actions/upload-artifact@v4 + with: + name: in_progress_execution_mem_report path: memory_report.json retention-days: 3 overwrite: true @@ -414,6 +428,50 @@ jobs: mv /home/runner/work/noir/noir/scripts/test_programs/execution_report.sh ./execution_report.sh ./execution_report.sh 1 1 + - name: Generate compilation report with averages + working-directory: ./test-repo/${{ matrix.project.path }} + if: ${{ matrix.project.take_average }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/compilation_report.sh ./compilation_report.sh + chmod +x ./compilation_report.sh + ./compilation_report.sh 1 1 + + - name: Generate execution report without averages + working-directory: ./test-repo/${{ matrix.project.path }} + if: ${{ !matrix.project.is_library && !matrix.project.take_average }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/execution_report.sh ./execution_report.sh + ./execution_report.sh 1 + + - name: Generate execution report with averages + working-directory: ./test-repo/${{ matrix.project.path }} + if: ${{ !matrix.project.is_library && matrix.project.take_average }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/execution_report.sh ./execution_report.sh + ./execution_report.sh 1 1 + + - name: Generate compilation report with averages + working-directory: ./test-repo/${{ matrix.project.path }} + if: ${{ matrix.project.take_average }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/compilation_report.sh ./compilation_report.sh + chmod +x ./compilation_report.sh + ./compilation_report.sh 1 1 + + - name: Generate execution report without averages + working-directory: ./test-repo/${{ matrix.project.path }} + if: ${{ !matrix.project.is_library && !matrix.project.take_average }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/execution_report.sh ./execution_report.sh + ./execution_report.sh 1 + + - name: Generate execution report with averages + working-directory: ./test-repo/${{ matrix.project.path }} + if: ${{ !matrix.project.is_library && matrix.project.take_average }} + run: | + mv /home/runner/work/noir/noir/scripts/test_programs/execution_report.sh ./execution_report.sh + ./execution_report.sh 1 1 + - name: Move compilation report id: compilation_report shell: bash @@ -479,11 +537,11 @@ jobs: - name: Parse compilation report id: compilation_report - uses: noir-lang/noir-bench-report@e408e131e96c3615b4f820d7d642360fb4d6e2f4 + uses: noir-lang/noir-bench-report@6ba151d7795042c4ff51864fbeb13c0a6a79246c with: report: compilation_report.json header: | - # Compilation Report + Compilation Report memory_report: false - name: Add memory report to sticky comment @@ -507,6 +565,8 @@ jobs: - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-inner } - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-reset } - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/private-kernel-tail } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-private } + - project: { repo: AztecProtocol/aztec-packages, path: noir-projects/noir-protocol-circuits/crates/rollup-base-public } name: External repo memory report - ${{ matrix.project.repo }}/${{ matrix.project.path }} steps: @@ -538,15 +598,38 @@ jobs: path: test-repo ref: ${{ matrix.project.ref }} - - name: Generate compilation report + - name: Generate compilation memory report working-directory: ./test-repo/${{ matrix.project.path }} run: | mv /home/runner/work/noir/noir/scripts/test_programs/memory_report.sh ./memory_report.sh - chmod +x ./memory_report.sh ./memory_report.sh 1 + # Rename the memory report as the execution report is about to write to the same file + cp memory_report.json compilation_memory_report.json + + - name: Generate execution memory report + working-directory: ./test-repo/${{ matrix.project.path }} + run: | + ./memory_report.sh 1 1 - name: Move compilation report - id: report + id: compilation_mem_report + shell: bash + run: | + PACKAGE_NAME=${{ matrix.project.path }} + PACKAGE_NAME=$(basename $PACKAGE_NAME) + mv ./test-repo/${{ matrix.project.path }}/compilation_memory_report.json ./memory_report_$PACKAGE_NAME.json + echo "memory_report_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT + + - name: Upload compilation memory report + uses: actions/upload-artifact@v4 + with: + name: compilation_mem_report_${{ steps.compilation_mem_report.outputs.memory_report_name }} + path: memory_report_${{ steps.compilation_mem_report.outputs.memory_report_name }}.json + retention-days: 3 + overwrite: true + + - name: Move execution report + id: execution_mem_report shell: bash run: | PACKAGE_NAME=${{ matrix.project.path }} @@ -554,16 +637,16 @@ jobs: mv ./test-repo/${{ matrix.project.path }}/memory_report.json ./memory_report_$PACKAGE_NAME.json echo "memory_report_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT - - name: Upload memory report + - name: Upload execution memory report uses: actions/upload-artifact@v4 with: - name: memory_report_${{ steps.report.outputs.memory_report_name }} - path: memory_report_${{ steps.report.outputs.memory_report_name }}.json + name: execution_mem_report_${{ steps.execution_mem_report.outputs.memory_report_name }} + path: memory_report_${{ steps.execution_mem_report.outputs.memory_report_name }}.json retention-days: 3 overwrite: true - upload_memory_report: - name: Upload memory report + upload_compilation_memory_report: + name: Upload compilation memory report needs: [generate_memory_report, external_repo_memory_report] # We want this job to run even if one variation of the matrix in `external_repo_memory_report` fails if: always() @@ -577,12 +660,12 @@ jobs: - name: Download initial memory report uses: actions/download-artifact@v4 with: - name: in_progress_memory_report + name: in_progress_compilation_mem_report - name: Download matrix memory reports uses: actions/download-artifact@v4 with: - pattern: memory_report_* + pattern: compilation_mem_report_* path: ./reports - name: Merge memory reports using jq @@ -590,21 +673,67 @@ jobs: mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh ./merge-bench-reports.sh memory_report - - name: Parse memory report - id: memory_report - uses: noir-lang/noir-bench-report@e408e131e96c3615b4f820d7d642360fb4d6e2f4 + - name: Parse compilation memory report + id: compilation_mem_report + uses: noir-lang/noir-bench-report@6ba151d7795042c4ff51864fbeb13c0a6a79246c with: report: memory_report.json header: | - # Memory Report + Compilation Memory Report memory_report: true - name: Add memory report to sticky comment if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' uses: marocchino/sticky-pull-request-comment@v2 with: - header: memory - message: ${{ steps.memory_report.outputs.markdown }} + header: compilation_memory + message: ${{ steps.compilation_mem_report.outputs.markdown }} + + upload_execution_memory_report: + name: Upload execution memory report + needs: [generate_memory_report, external_repo_memory_report] + # We want this job to run even if one variation of the matrix in `external_repo_memory_report` fails + if: always() + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v4 + + - name: Download initial memory report + uses: actions/download-artifact@v4 + with: + name: in_progress_execution_mem_report + + - name: Download matrix memory reports + uses: actions/download-artifact@v4 + with: + pattern: execution_mem_report_* + path: ./reports + + - name: Merge memory reports using jq + run: | + mv ./.github/scripts/merge-bench-reports.sh merge-bench-reports.sh + ./merge-bench-reports.sh memory_report + # Rename the memory report as to not clash with the compilation memory report file name + cp memory_report.json execution_memory_report.json + + - name: Parse execution memory report + id: execution_mem_report + uses: noir-lang/noir-bench-report@6ba151d7795042c4ff51864fbeb13c0a6a79246c + with: + report: execution_memory_report.json + header: | + Execution Memory Report + memory_report: true + + - name: Add execution memory report to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + header: execution_memory + message: ${{ steps.execution_mem_report.outputs.markdown }} upload_execution_report: name: Upload execution report @@ -636,11 +765,11 @@ jobs: - name: Parse execution report id: execution_report - uses: noir-lang/noir-bench-report@e408e131e96c3615b4f820d7d642360fb4d6e2f4 + uses: noir-lang/noir-bench-report@6ba151d7795042c4ff51864fbeb13c0a6a79246c with: report: execution_report.json header: | - # Execution Report + Execution Report execution_report: true - name: Add memory report to sticky comment diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index a29cb44acd4..f8d09d8d39c 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -31,7 +31,7 @@ dependencies = [ "ark-bls12-381", "ark-bn254", "ark-ff", - "cfg-if 1.0.0", + "cfg-if", "hex", "num-bigint", "proptest", @@ -88,9 +88,9 @@ dependencies = [ "nargo", "paste", "proptest", - "rand 0.8.5", + "rand", "thiserror", - "toml 0.7.8", + "toml", "tracing-appender", "tracing-subscriber", ] @@ -104,7 +104,7 @@ dependencies = [ "build-data", "console_error_panic_hook", "const-str", - "getrandom 0.2.15", + "getrandom", "gloo-utils", "js-sys", "pkg-config", @@ -143,8 +143,8 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", - "getrandom 0.2.15", + "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -370,7 +370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ "num-traits", - "rand 0.8.5", + "rand", ] [[package]] @@ -422,7 +422,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138985dd8aefbefeaa66b01b7f5b2b6b4c333fcef1cc5f32c63a2aabe37d6de3" dependencies = [ - "futures 0.3.31", + "futures", "lsp-types 0.94.1", "pin-project-lite", "rustix", @@ -436,6 +436,23 @@ dependencies = [ "waitpid-any", ] +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.4.0" @@ -450,7 +467,7 @@ checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide 0.7.4", "object", @@ -463,12 +480,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -573,7 +584,7 @@ dependencies = [ "arrayref", "arrayvec", "cc", - "cfg-if 1.0.0", + "cfg-if", "constant_time_eq", ] @@ -595,7 +606,7 @@ dependencies = [ "ff 0.12.1", "group 0.12.1", "pairing", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -682,38 +693,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" -[[package]] -name = "camino" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "cast" version = "0.3.0" @@ -730,10 +709,10 @@ dependencies = [ ] [[package]] -name = "cfg-if" -version = "0.1.10" +name = "cesu8" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" @@ -869,7 +848,7 @@ checksum = "fc4159b76af02757139baf42c0c971c6dc155330999fbfd8eddb29b97fb2db68" dependencies = [ "codespan-reporting", "lsp-types 0.88.0", - "url 2.5.4", + "url", ] [[package]] @@ -916,6 +895,16 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "comma" version = "1.0.0" @@ -940,7 +929,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen", ] @@ -982,12 +971,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "convert_case" version = "0.6.0" @@ -997,6 +980,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1009,7 +1002,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1027,7 +1020,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1113,7 +1106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ "generic-array", - "rand_core 0.6.4", + "rand_core", "subtle", "zeroize", ] @@ -1201,12 +1194,12 @@ version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", "hashbrown 0.14.5", "lock_api", "once_cell", - "parking_lot_core 0.9.10", + "parking_lot_core", ] [[package]] @@ -1249,19 +1242,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "convert_case 0.4.0", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.87", -] - [[package]] name = "difflib" version = "0.4.0" @@ -1294,7 +1274,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] @@ -1384,7 +1364,7 @@ dependencies = [ "generic-array", "group 0.12.1", "pkcs8", - "rand_core 0.6.4", + "rand_core", "sec1", "subtle", "zeroize", @@ -1495,7 +1475,7 @@ version = "3.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "rustix", "windows-sys 0.48.0", ] @@ -1507,7 +1487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" dependencies = [ "bitvec", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -1518,7 +1498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "bitvec", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -1556,7 +1536,7 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "libredox 0.1.3", "windows-sys 0.59.0", @@ -1620,7 +1600,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "percent-encoding 2.3.1", + "percent-encoding", ] [[package]] @@ -1638,12 +1618,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" -[[package]] -name = "futures" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" - [[package]] name = "futures" version = "0.3.31" @@ -1652,7 +1626,6 @@ checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -1675,18 +1648,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", - "num_cpus", -] - [[package]] name = "futures-io" version = "0.3.31" @@ -1722,7 +1683,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures 0.1.31", "futures-channel", "futures-core", "futures-io", @@ -1754,27 +1714,16 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - [[package]] name = "getrandom" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] @@ -1835,7 +1784,7 @@ checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ "ff 0.12.1", "memuse", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -1846,17 +1795,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff 0.13.0", - "rand_core 0.6.4", + "rand_core", "subtle", ] +[[package]] +name = "h2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crunchy", ] @@ -1879,7 +1847,7 @@ dependencies = [ "ff 0.12.1", "group 0.12.1", "pasta_curves 0.4.1", - "rand_core 0.6.4", + "rand_core", "rayon", ] @@ -1960,9 +1928,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.12" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1971,12 +1939,24 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.6" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", + "futures-util", "http", + "http-body", "pin-project-lite", ] @@ -1994,25 +1974,60 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.31" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c08302e8fa335b151b788c775ff56e7a03ae64ff85c548ee820fecb70356e85" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "log", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", "socket2", "tokio", "tower-service", "tracing", - "want", ] [[package]] @@ -2168,17 +2183,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "1.0.3" @@ -2223,7 +2227,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" dependencies = [ "bitmaps", - "rand_core 0.6.4", + "rand_core", "rand_xoshiro", "serde", "sized-chunks", @@ -2326,15 +2330,6 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "is-terminal" version = "0.4.13" @@ -2372,126 +2367,147 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "js-sys" -version = "0.3.63" +name = "jni" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" dependencies = [ - "wasm-bindgen", + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", ] [[package]] -name = "jsonrpc" -version = "0.16.0" +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efde8d2422fb79ed56db1d3aea8fa5b583351d15a26770cdee2f88813dd702" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ - "base64 0.13.1", - "minreq", - "serde", - "serde_json", + "wasm-bindgen", ] [[package]] -name = "jsonrpc-client-transports" -version = "18.0.0" +name = "jsonrpsee" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b99d4207e2a04fb4581746903c2bb7eb376f88de9c699d0f3e10feeac0cd3a" +checksum = "c5c71d8c1a731cc4227c2f698d377e7848ca12c8a48866fc5e6951c43a4db843" dependencies = [ - "derive_more", - "futures 0.3.31", - "jsonrpc-core", - "jsonrpc-pubsub", - "log", - "serde", - "serde_json", - "url 1.7.2", + "jsonrpsee-core", + "jsonrpsee-http-client", + "jsonrpsee-proc-macros", + "jsonrpsee-server", + "jsonrpsee-types", + "tokio", + "tracing", ] [[package]] -name = "jsonrpc-core" -version = "18.0.0" +name = "jsonrpsee-core" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +checksum = "f2882f6f8acb9fdaec7cefc4fd607119a9bd709831df7d7672a1d3b644628280" dependencies = [ - "futures 0.3.31", - "futures-executor", + "async-trait", + "bytes", "futures-util", - "log", + "http", + "http-body", + "http-body-util", + "jsonrpsee-types", + "parking_lot", + "rand", + "rustc-hash 2.1.0", "serde", - "serde_derive", "serde_json", + "thiserror", + "tokio", + "tracing", ] [[package]] -name = "jsonrpc-core-client" -version = "18.0.0" +name = "jsonrpsee-http-client" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b51da17abecbdab3e3d4f26b01c5ec075e88d3abe3ab3b05dc9aa69392764ec0" +checksum = "b3638bc4617f96675973253b3a45006933bde93c2fd8a6170b33c777cc389e5b" dependencies = [ - "futures 0.3.31", - "jsonrpc-client-transports", + "async-trait", + "base64 0.22.1", + "http-body", + "hyper", + "hyper-rustls", + "hyper-util", + "jsonrpsee-core", + "jsonrpsee-types", + "rustls", + "rustls-platform-verifier", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "tracing", + "url", ] [[package]] -name = "jsonrpc-derive" -version = "18.0.0" +name = "jsonrpsee-proc-macros" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b939a78fa820cdfcb7ee7484466746a7377760970f6f9c6fe19f9edcc8a38d2" +checksum = "c06c01ae0007548e73412c08e2285ffe5d723195bf268bce67b1b77c3bb2a14d" dependencies = [ + "heck 0.5.0", "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] -name = "jsonrpc-http-server" -version = "18.0.0" +name = "jsonrpsee-server" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1dea6e07251d9ce6a552abfb5d7ad6bc290a4596c8dcc3d795fae2bbdc1f3ff" +checksum = "82ad8ddc14be1d4290cd68046e7d1d37acd408efed6d3ca08aefcc3ad6da069c" dependencies = [ - "futures 0.3.31", + "futures-util", + "http", + "http-body", + "http-body-util", "hyper", - "jsonrpc-core", - "jsonrpc-server-utils", - "log", - "net2", - "parking_lot 0.11.2", - "unicase", -] - -[[package]] -name = "jsonrpc-pubsub" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240f87695e6c6f62fb37f05c02c04953cf68d6408b8c1c89de85c7a0125b1011" -dependencies = [ - "futures 0.3.31", - "jsonrpc-core", - "lazy_static", - "log", - "parking_lot 0.11.2", - "rand 0.7.3", + "hyper-util", + "jsonrpsee-core", + "jsonrpsee-types", + "pin-project", + "route-recognizer", "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", ] [[package]] -name = "jsonrpc-server-utils" -version = "18.0.0" +name = "jsonrpsee-types" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4fdea130485b572c39a460d50888beb00afb3e35de23ccd7fad8ff19f0e0d4" +checksum = "a178c60086f24cc35bb82f57c651d0d25d99c4742b4d335de04e97fa1f08a8a1" dependencies = [ - "bytes", - "futures 0.3.31", - "globset", - "jsonrpc-core", - "lazy_static", - "log", - "tokio", - "tokio-stream", - "tokio-util 0.6.10", - "unicase", + "http", + "serde", + "serde_json", + "thiserror", ] [[package]] @@ -2504,7 +2520,7 @@ dependencies = [ "bls12_381", "ff 0.12.1", "group 0.12.1", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -2514,7 +2530,7 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ecdsa", "elliptic-curve", "sha2", @@ -2657,7 +2673,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url 2.5.4", + "url", ] [[package]] @@ -2670,7 +2686,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "url 2.5.4", + "url", ] [[package]] @@ -2682,12 +2698,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "memchr" version = "2.7.4" @@ -2736,17 +2746,6 @@ dependencies = [ "adler2", ] -[[package]] -name = "minreq" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763d142cdff44aaadd9268bebddb156ef6c65a0e13486bb81673cf2d8739f9b0" -dependencies = [ - "log", - "serde", - "serde_json", -] - [[package]] name = "mio" version = "0.8.11" @@ -2755,7 +2754,7 @@ checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -2767,7 +2766,7 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.52.0", ] @@ -2778,11 +2777,7 @@ dependencies = [ "acvm", "fm", "iter-extended", - "jsonrpc", - "jsonrpc-core", - "jsonrpc-core-client", - "jsonrpc-derive", - "jsonrpc-http-server", + "jsonrpsee", "noir_fuzzer", "noirc_abi", "noirc_driver", @@ -2790,10 +2785,12 @@ dependencies = [ "noirc_frontend", "noirc_printable_type", "proptest", - "rand 0.8.5", + "rand", "rayon", "serde", + "serde_json", "thiserror", + "tokio", "tracing", "walkdir", ] @@ -2850,12 +2847,11 @@ dependencies = [ "tempfile", "termcolor", "termion", - "test-binary", "test-case", "thiserror", "tokio", - "tokio-util 0.7.12", - "toml 0.7.8", + "tokio-util", + "toml", "tower", "tracing-appender", "tracing-subscriber", @@ -2869,7 +2865,7 @@ dependencies = [ "serde", "similar-asserts", "thiserror", - "toml 0.7.8", + "toml", ] [[package]] @@ -2886,19 +2882,8 @@ dependencies = [ "tempfile", "test-case", "thiserror", - "toml 0.7.8", - "url 2.5.4", -] - -[[package]] -name = "net2" -version = "0.2.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi", + "toml", + "url", ] [[package]] @@ -2918,7 +2903,7 @@ checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ "bitflags 1.3.2", "cc", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset", ] @@ -2931,7 +2916,7 @@ checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ "autocfg", "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset", "pin-utils", @@ -2944,7 +2929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "libc", ] @@ -2980,7 +2965,7 @@ dependencies = [ "noirc_abi", "noirc_artifacts", "proptest", - "rand 0.8.5", + "rand", ] [[package]] @@ -3002,7 +2987,7 @@ dependencies = [ "acvm", "async-lsp", "codespan-lsp", - "convert_case 0.6.0", + "convert_case", "fm", "fxhash", "lsp-types 0.94.1", @@ -3056,7 +3041,7 @@ dependencies = [ "build-data", "console_error_panic_hook", "fm", - "getrandom 0.2.15", + "getrandom", "gloo-utils", "js-sys", "nargo", @@ -3088,7 +3073,7 @@ dependencies = [ "strum", "strum_macros", "thiserror", - "toml 0.7.8", + "toml", ] [[package]] @@ -3098,7 +3083,7 @@ dependencies = [ "acvm", "build-data", "console_error_panic_hook", - "getrandom 0.2.15", + "getrandom", "gloo-utils", "iter-extended", "js-sys", @@ -3169,7 +3154,7 @@ version = "1.0.0-beta.1" dependencies = [ "acvm", "bn254_blackbox_solver", - "cfg-if 1.0.0", + "cfg-if", "chrono", "fxhash", "im", @@ -3198,7 +3183,7 @@ dependencies = [ "acvm", "base64 0.21.7", "bn254_blackbox_solver", - "cfg-if 1.0.0", + "cfg-if", "fm", "im", "iter-extended", @@ -3211,7 +3196,7 @@ dependencies = [ "proptest", "proptest-derive 0.5.0", "rangemap", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "serde_json", "small-ord-set", @@ -3227,11 +3212,7 @@ name = "noirc_printable_type" version = "1.0.0-beta.1" dependencies = [ "acvm", - "iter-extended", - "jsonrpc", "serde", - "serde_json", - "thiserror", ] [[package]] @@ -3269,7 +3250,7 @@ dependencies = [ "file-id", "log", "notify", - "parking_lot 0.12.3", + "parking_lot", "walkdir", ] @@ -3328,16 +3309,6 @@ dependencies = [ "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - [[package]] name = "numtoa" version = "0.1.0" @@ -3365,6 +3336,12 @@ version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + [[package]] name = "overload" version = "0.1.1" @@ -3397,17 +3374,6 @@ dependencies = [ "group 0.12.1", ] -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - [[package]] name = "parking_lot" version = "0.12.3" @@ -3415,21 +3381,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "parking_lot_core", ] [[package]] @@ -3438,7 +3390,7 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "redox_syscall 0.5.7", "smallvec", @@ -3455,7 +3407,7 @@ dependencies = [ "ff 0.12.1", "group 0.12.1", "lazy_static", - "rand 0.8.5", + "rand", "static_assertions", "subtle", ] @@ -3470,7 +3422,7 @@ dependencies = [ "ff 0.13.0", "group 0.13.0", "lazy_static", - "rand 0.8.5", + "rand", "static_assertions", "subtle", ] @@ -3481,12 +3433,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.3.1" @@ -3521,7 +3467,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" dependencies = [ "phf_shared", - "rand 0.8.5", + "rand", ] [[package]] @@ -3547,6 +3493,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "pin-project-lite" version = "0.2.15" @@ -3617,7 +3583,7 @@ checksum = "ebbe2f8898beba44815fdc9e5a4ae9c929e21c5dc29b0c774a15555f7f58d6d0" dependencies = [ "aligned-vec", "backtrace", - "cfg-if 1.0.0", + "cfg-if", "criterion", "findshlibs", "inferno", @@ -3625,7 +3591,7 @@ dependencies = [ "log", "nix 0.26.4", "once_cell", - "parking_lot 0.12.3", + "parking_lot", "smallvec", "symbolic-demangle", "tempfile", @@ -3698,11 +3664,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "0.1.5" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml 0.5.11", + "toml_edit 0.22.22", ] [[package]] @@ -3731,8 +3697,8 @@ dependencies = [ "bitflags 2.6.0", "lazy_static", "num-traits", - "rand 0.8.5", - "rand_chacha 0.3.1", + "rand", + "rand_chacha", "rand_xorshift", "regex-syntax 0.8.5", "rusty-fork", @@ -3802,19 +3768,6 @@ dependencies = [ "nibble_vec", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", -] - [[package]] name = "rand" version = "0.8.5" @@ -3822,18 +3775,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", + "rand_chacha", + "rand_core", ] [[package]] @@ -3843,16 +3786,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", + "rand_core", ] [[package]] @@ -3861,16 +3795,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", + "getrandom", ] [[package]] @@ -3879,7 +3804,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" dependencies = [ - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -3888,7 +3813,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -3917,15 +3842,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3956,7 +3872,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom", "libredox 0.1.3", "thiserror", ] @@ -4038,6 +3954,27 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "route-recognizer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" + [[package]] name = "rust-embed" version = "6.8.1" @@ -4084,6 +4021,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" + [[package]] name = "rustc_version" version = "0.4.1" @@ -4106,6 +4049,87 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" + +[[package]] +name = "rustls-platform-verifier" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-roots", + "winapi", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.18" @@ -4131,7 +4155,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db7826789c0e25614b03e5a54a0717a86f9ff6e6e5247f92b369472869320039" dependencies = [ "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "clipboard-win", "dirs-next", "fd-lock", @@ -4226,6 +4250,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -4252,14 +4285,35 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "num-bigint", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -dependencies = [ - "serde", -] [[package]] name = "serde" @@ -4377,13 +4431,24 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest", ] @@ -4426,7 +4491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ "digest", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -4517,6 +4582,22 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "soketto" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e859df029d160cb88608f5d7df7fb4753fd20fdfb4de5644f3d8b8440841721" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures", + "http", + "httparse", + "log", + "rand", + "sha1", +] + [[package]] name = "spin" version = "0.9.8" @@ -4656,7 +4737,7 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "once_cell", "rustix", @@ -4701,19 +4782,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" -[[package]] -name = "test-binary" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c7cb854285c40b61c0fade358bf63a2bb1226688a1ea11432ea65349209e6e3" -dependencies = [ - "camino", - "cargo_metadata", - "once_cell", - "paste", - "thiserror", -] - [[package]] name = "test-case" version = "3.3.1" @@ -4729,7 +4797,7 @@ version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "proc-macro2", "quote", "syn 2.0.87", @@ -4794,7 +4862,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] @@ -4849,26 +4917,11 @@ dependencies = [ "serde_json", ] -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -4892,28 +4945,25 @@ dependencies = [ ] [[package]] -name = "tokio-stream" -version = "0.1.16" +name = "tokio-rustls" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "futures-core", - "pin-project-lite", + "rustls", "tokio", ] [[package]] -name = "tokio-util" -version = "0.6.10" +name = "tokio-stream" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ - "bytes", "futures-core", - "futures-sink", - "log", "pin-project-lite", "tokio", + "tokio-util", ] [[package]] @@ -4930,15 +4980,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.7.8" @@ -4948,7 +4989,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -4970,7 +5011,18 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "toml_datetime", + "winnow 0.6.20", ] [[package]] @@ -4979,6 +5031,10 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", "tower-layer", "tower-service", "tracing", @@ -5141,18 +5197,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" -[[package]] -name = "unicase" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" - -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - [[package]] name = "unicode-ident" version = "1.0.13" @@ -5165,15 +5209,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" -[[package]] -name = "unicode-normalization" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -5193,15 +5228,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] -name = "url" -version = "1.7.2" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" @@ -5210,8 +5240,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 1.0.3", - "percent-encoding 2.3.1", + "idna", + "percent-encoding", "serde", ] @@ -5289,12 +5319,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5307,7 +5331,7 @@ version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "serde", "serde_json", "wasm-bindgen-macro", @@ -5334,7 +5358,7 @@ version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -5403,6 +5427,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -5600,6 +5633,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "write16" version = "1.0.0" @@ -5741,7 +5783,7 @@ dependencies = [ "blake2", "bls12_381", "byteorder", - "cfg-if 1.0.0", + "cfg-if", "group 0.12.1", "group 0.13.0", "halo2", @@ -5749,7 +5791,7 @@ dependencies = [ "jubjub", "lazy_static", "pasta_curves 0.5.1", - "rand 0.8.5", + "rand", "serde", "sha2", "sha3", diff --git a/noir/noir-repo/Cargo.toml b/noir/noir-repo/Cargo.toml index 5e31693b09b..53a28b8002d 100644 --- a/noir/noir-repo/Cargo.toml +++ b/noir/noir-repo/Cargo.toml @@ -148,7 +148,7 @@ num-traits = "0.2" similar-asserts = "1.5.0" tempfile = "3.6.0" test-case = "3.3.1" -jsonrpc = { version = "0.16.0", features = ["minreq_http"] } +jsonrpsee = { version = "0.24.7", features = ["client-core"] } flate2 = "1.0.24" color-eyre = "0.6.2" rand = "0.8.5" @@ -159,7 +159,7 @@ sha2 = { version = "0.10.6", features = ["compress"] } sha3 = "0.10.6" strum = "0.24" strum_macros = "0.24" - +tokio = "1.42" im = { version = "15.1", features = ["serde"] } tracing = "0.1.40" tracing-web = "0.1.3" diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 23d8b425349..0c8d8affeb1 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -22,7 +22,7 @@ use super::{ value::{Value, ValueId}, }; -mod binary; +pub(crate) mod binary; mod call; mod cast; mod constrain; diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs index 81f2f3b1e01..ce65343c7ef 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/binary.rs @@ -294,7 +294,7 @@ impl Binary { } /// Evaluate a binary operation with constant arguments. -fn eval_constant_binary_op( +pub(crate) fn eval_constant_binary_op( lhs: FieldElement, rhs: FieldElement, operator: BinaryOp, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs index aec172dddcd..cbaacf1d70e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/flatten_cfg.rs @@ -818,13 +818,10 @@ mod test { use acvm::acir::AcirField; use crate::ssa::{ - function_builder::FunctionBuilder, ir::{ dfg::DataFlowGraph, function::Function, - instruction::{BinaryOp, Instruction, TerminatorInstruction}, - map::Id, - types::Type, + instruction::{Instruction, TerminatorInstruction}, value::{Value, ValueId}, }, opt::assert_normalized_ssa_equals, @@ -1337,104 +1334,50 @@ mod test { // Regression test for #1826. Ensures the `else` branch does not see the stores of the // `then` branch. // - // fn main f1 { - // b0(): - // v0 = allocate - // store Field 0 at v0 - // v2 = allocate - // store Field 2 at v2 - // v4 = load v2 - // v5 = lt v4, Field 2 - // jmpif v5 then: b1, else: b2 - // b1(): - // v24 = load v0 - // v25 = load v2 - // v26 = mul v25, Field 10 - // v27 = add v24, v26 - // store v27 at v0 - // v28 = load v2 - // v29 = add v28, Field 1 - // store v29 at v2 - // jmp b5() - // b5(): - // v14 = load v0 - // return v14 - // b2(): - // v6 = load v2 - // v8 = lt v6, Field 4 - // jmpif v8 then: b3, else: b4 - // b3(): - // v16 = load v0 - // v17 = load v2 - // v19 = mul v17, Field 100 - // v20 = add v16, v19 - // store v20 at v0 - // v21 = load v2 - // v23 = add v21, Field 1 - // store v23 at v2 - // jmp b4() - // b4(): - // jmp b5() - // } - let main_id = Id::test_new(0); - let mut builder = FunctionBuilder::new("main".into(), main_id); - - let b1 = builder.insert_block(); - let b2 = builder.insert_block(); - let b3 = builder.insert_block(); - let b4 = builder.insert_block(); - let b5 = builder.insert_block(); - - let zero = builder.field_constant(0u128); - let one = builder.field_constant(1u128); - let two = builder.field_constant(2u128); - let four = builder.field_constant(4u128); - let ten = builder.field_constant(10u128); - let one_hundred = builder.field_constant(100u128); - - let v0 = builder.insert_allocate(Type::field()); - builder.insert_store(v0, zero); - let v2 = builder.insert_allocate(Type::field()); - builder.insert_store(v2, two); - let v4 = builder.insert_load(v2, Type::field()); - let v5 = builder.insert_binary(v4, BinaryOp::Lt, two); - builder.terminate_with_jmpif(v5, b1, b2); - - builder.switch_to_block(b1); - let v24 = builder.insert_load(v0, Type::field()); - let v25 = builder.insert_load(v2, Type::field()); - let v26 = builder.insert_binary(v25, BinaryOp::Mul, ten); - let v27 = builder.insert_binary(v24, BinaryOp::Add, v26); - builder.insert_store(v0, v27); - let v28 = builder.insert_load(v2, Type::field()); - let v29 = builder.insert_binary(v28, BinaryOp::Add, one); - builder.insert_store(v2, v29); - builder.terminate_with_jmp(b5, vec![]); - - builder.switch_to_block(b5); - let v14 = builder.insert_load(v0, Type::field()); - builder.terminate_with_return(vec![v14]); - - builder.switch_to_block(b2); - let v6 = builder.insert_load(v2, Type::field()); - let v8 = builder.insert_binary(v6, BinaryOp::Lt, four); - builder.terminate_with_jmpif(v8, b3, b4); - - builder.switch_to_block(b3); - let v16 = builder.insert_load(v0, Type::field()); - let v17 = builder.insert_load(v2, Type::field()); - let v19 = builder.insert_binary(v17, BinaryOp::Mul, one_hundred); - let v20 = builder.insert_binary(v16, BinaryOp::Add, v19); - builder.insert_store(v0, v20); - let v21 = builder.insert_load(v2, Type::field()); - let v23 = builder.insert_binary(v21, BinaryOp::Add, one); - builder.insert_store(v2, v23); - builder.terminate_with_jmp(b4, vec![]); - - builder.switch_to_block(b4); - builder.terminate_with_jmp(b5, vec![]); - - let ssa = builder.finish().flatten_cfg().mem2reg().fold_constants(); + let src = " + acir(inline) fn main f0 { + b0(): + v0 = allocate -> &mut Field + store Field 0 at v0 + v2 = allocate -> &mut Field + store Field 2 at v2 + v4 = load v2 -> Field + v5 = lt v4, Field 2 + jmpif v5 then: b4, else: b1 + b1(): + v6 = load v2 -> Field + v8 = lt v6, Field 4 + jmpif v8 then: b2, else: b3 + b2(): + v9 = load v0 -> Field + v10 = load v2 -> Field + v12 = mul v10, Field 100 + v13 = add v9, v12 + store v13 at v0 + v14 = load v2 -> Field + v16 = add v14, Field 1 + store v16 at v2 + jmp b3() + b3(): + jmp b5() + b4(): + v17 = load v0 -> Field + v18 = load v2 -> Field + v20 = mul v18, Field 10 + v21 = add v17, v20 + store v21 at v0 + v22 = load v2 -> Field + v23 = add v22, Field 1 + store v23 at v2 + jmp b5() + b5(): + v24 = load v0 -> Field + return v24 + }"; + + let ssa = Ssa::from_str(src).unwrap(); + + let ssa = ssa.flatten_cfg().mem2reg().fold_constants(); let main = ssa.main(); @@ -1451,6 +1394,18 @@ mod test { } _ => unreachable!("Should have terminator instruction"), } + + let expected = " + acir(inline) fn main f0 { + b0(): + v0 = allocate -> &mut Field + v1 = allocate -> &mut Field + enable_side_effects u1 1 + return Field 200 + } + "; + + assert_normalized_ssa_equals(ssa, expected); } #[test] diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/loop_invariant.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/loop_invariant.rs index c188ed1f80f..0a3c18c1b1e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/loop_invariant.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/loop_invariant.rs @@ -15,7 +15,7 @@ use crate::ssa::{ basic_block::BasicBlockId, function::Function, function_inserter::FunctionInserter, - instruction::{Instruction, InstructionId}, + instruction::{binary::eval_constant_binary_op, BinaryOp, Instruction, InstructionId}, types::Type, value::ValueId, }, @@ -207,6 +207,7 @@ impl<'f> LoopInvariantContext<'f> { let can_be_deduplicated = instruction.can_be_deduplicated(self.inserter.function, false) || matches!(instruction, Instruction::MakeArray { .. }) + || matches!(instruction, Instruction::Binary(_)) || self.can_be_deduplicated_from_upper_bound(&instruction); is_loop_invariant && can_be_deduplicated @@ -231,6 +232,31 @@ impl<'f> LoopInvariantContext<'f> { false } } + Instruction::Binary(binary) => { + if !matches!(binary.operator, BinaryOp::Add | BinaryOp::Mul) { + return false; + } + + let operand_type = + self.inserter.function.dfg.type_of_value(binary.lhs).unwrap_numeric(); + + let lhs_const = + self.inserter.function.dfg.get_numeric_constant_with_type(binary.lhs); + let rhs_const = + self.inserter.function.dfg.get_numeric_constant_with_type(binary.rhs); + let (lhs, rhs) = match ( + lhs_const, + rhs_const, + self.outer_induction_variables.get(&binary.lhs), + self.outer_induction_variables.get(&binary.rhs), + ) { + (Some((lhs, _)), None, None, Some(upper_bound)) => (lhs, *upper_bound), + (None, Some((rhs, _)), Some(upper_bound), None) => (*upper_bound, rhs), + _ => return false, + }; + + eval_constant_binary_op(lhs, rhs, binary.operator, operand_type).is_some() + } _ => false, } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index e7953aab5a4..eff48ce22a6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -500,6 +500,9 @@ impl<'a> ModCollector<'a> { .def_interner .push_function_definition(func_id, modifiers, trait_id.0, location); + let referenced = ReferenceId::Function(func_id); + context.def_interner.add_definition_location(referenced, Some(trait_id.0)); + if !trait_item.doc_comments.is_empty() { context.def_interner.set_doc_comments( ReferenceId::Function(func_id), @@ -1222,7 +1225,11 @@ pub(crate) fn collect_trait_impl_items( for item in std::mem::take(&mut trait_impl.items) { match item.item.kind { - TraitImplItemKind::Function(impl_method) => { + TraitImplItemKind::Function(mut impl_method) => { + // Regardless of what visibility was on the source code, treat it as public + // (a warning is produced during parsing for this) + impl_method.def.visibility = ItemVisibility::Public; + let func_id = interner.push_empty_fn(); let location = Location::new(impl_method.span(), file_id); interner.push_function(func_id, &impl_method.def, module, location); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs index 7cb8731593b..32cacf5e4ed 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs @@ -71,6 +71,8 @@ pub enum ParserErrorReason { PatternInTraitFunctionParameter, #[error("Patterns aren't allowed in a trait impl's associated constants")] PatternInAssociatedConstant, + #[error("Visibility is ignored on a trait method")] + TraitVisibilityIgnored, #[error("Visibility is ignored on a trait impl method")] TraitImplVisibilityIgnored, #[error("comptime keyword is deprecated")] @@ -183,11 +185,8 @@ impl ParserError { } pub fn is_warning(&self) -> bool { - matches!( - self.reason(), - Some(ParserErrorReason::ExperimentalFeature(_)) - | Some(ParserErrorReason::MissingSafetyComment) - ) + let diagnostic: Diagnostic = self.into(); + diagnostic.is_warning() } } @@ -264,6 +263,9 @@ impl<'a> From<&'a ParserError> for Diagnostic { ParserErrorReason::ExperimentalFeature(_) => { Diagnostic::simple_warning(reason.to_string(), "".into(), error.span) } + ParserErrorReason::TraitVisibilityIgnored => { + Diagnostic::simple_warning(reason.to_string(), "".into(), error.span) + } ParserErrorReason::TraitImplVisibilityIgnored => { Diagnostic::simple_warning(reason.to_string(), "".into(), error.span) } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/impls.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/impls.rs index 8e6b3bae0e9..278c20e1e27 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/impls.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/impls.rs @@ -245,7 +245,7 @@ impl<'a> Parser<'a> { let noir_function = self.parse_function( attributes, - ItemVisibility::Public, + modifiers.visibility, modifiers.comptime.is_some(), modifiers.unconstrained.is_some(), true, // allow_self @@ -482,7 +482,7 @@ mod tests { panic!("Expected function"); }; assert_eq!(function.def.name.to_string(), "foo"); - assert_eq!(function.def.visibility, ItemVisibility::Public); + assert_eq!(function.def.visibility, ItemVisibility::Private); } #[test] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs index e03b629e9ea..6f6a9bab960 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser/traits.rs @@ -225,6 +225,10 @@ impl<'a> Parser<'a> { false, // allow mut ); + if modifiers.visibility != ItemVisibility::Private { + self.push_error(ParserErrorReason::TraitVisibilityIgnored, modifiers.visibility_span); + } + if !self.eat_keyword(Keyword::Fn) { self.modifiers_not_followed_by_an_item(modifiers); return None; @@ -285,7 +289,11 @@ mod tests { use crate::{ ast::{NoirTrait, NoirTraitImpl, TraitItem}, parser::{ - parser::{parse_program, tests::expect_no_errors, ParserErrorReason}, + parser::{ + parse_program, + tests::{expect_no_errors, get_single_error, get_source_with_error_span}, + ParserErrorReason, + }, ItemKind, }, }; @@ -513,7 +521,19 @@ mod tests { } #[test] - fn parse_trait_inheirtance() { + fn parse_trait_function_with_visibility() { + let src = " + trait Foo { pub fn foo(); } + ^^^ + "; + let (src, span) = get_source_with_error_span(src); + let (_module, errors) = parse_program(&src); + let error = get_single_error(&errors, span); + assert!(error.to_string().contains("Visibility is ignored on a trait method")); + } + + #[test] + fn parse_trait_inheritance() { let src = "trait Foo: Bar + Baz {}"; let noir_trait = parse_trait_no_errors(src); assert_eq!(noir_trait.bounds.len(), 2); diff --git a/noir/noir-repo/compiler/noirc_printable_type/Cargo.toml b/noir/noir-repo/compiler/noirc_printable_type/Cargo.toml index 8d0574aad64..a1eae750b1f 100644 --- a/noir/noir-repo/compiler/noirc_printable_type/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_printable_type/Cargo.toml @@ -13,10 +13,6 @@ workspace = true [dependencies] acvm.workspace = true -iter-extended.workspace = true serde.workspace = true -serde_json.workspace = true -thiserror.workspace = true -jsonrpc.workspace = true [dev-dependencies] diff --git a/noir/noir-repo/compiler/noirc_printable_type/src/lib.rs b/noir/noir-repo/compiler/noirc_printable_type/src/lib.rs index 6ae187da27f..eb74d2470fb 100644 --- a/noir/noir-repo/compiler/noirc_printable_type/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_printable_type/src/lib.rs @@ -1,10 +1,13 @@ +#![forbid(unsafe_code)] +#![warn(unused_crate_dependencies, unused_extern_crates)] +#![warn(unreachable_pub)] +#![warn(clippy::semicolon_if_nothing_returned)] + use std::{collections::BTreeMap, str}; -use acvm::{acir::AcirField, brillig_vm::brillig::ForeignCallParam}; -use iter_extended::vecmap; +use acvm::AcirField; use serde::{Deserialize, Serialize}; -use thiserror::Error; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(tag = "kind", rename_all = "lowercase")] @@ -66,96 +69,23 @@ pub enum PrintableValueDisplay { Plain(PrintableValue, PrintableType), FmtString(String, Vec<(PrintableValue, PrintableType)>), } - -#[derive(Debug, Error)] -pub enum ForeignCallError { - #[error("No handler could be found for foreign call `{0}`")] - NoHandler(String), - - #[error("Foreign call inputs needed for execution are missing")] - MissingForeignCallInputs, - - #[error("Could not parse PrintableType argument. {0}")] - ParsingError(#[from] serde_json::Error), - - #[error("Failed calling external resolver. {0}")] - ExternalResolverError(#[from] jsonrpc::Error), - - #[error("Assert message resolved after an unsatisified constrain. {0}")] - ResolvedAssertMessage(String), -} - -impl TryFrom<&[ForeignCallParam]> for PrintableValueDisplay { - type Error = ForeignCallError; - - fn try_from(foreign_call_inputs: &[ForeignCallParam]) -> Result { - let (is_fmt_str, foreign_call_inputs) = - foreign_call_inputs.split_last().ok_or(ForeignCallError::MissingForeignCallInputs)?; - - if is_fmt_str.unwrap_field().is_one() { - convert_fmt_string_inputs(foreign_call_inputs) - } else { - convert_string_inputs(foreign_call_inputs) +impl std::fmt::Display for PrintableValueDisplay { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Plain(value, typ) => { + let output_string = to_string(value, typ).ok_or(std::fmt::Error)?; + write!(fmt, "{output_string}") + } + Self::FmtString(template, values) => { + let mut values_iter = values.iter(); + write_template_replacing_interpolations(template, fmt, || { + values_iter.next().and_then(|(value, typ)| to_string(value, typ)) + }) + } } } } -fn convert_string_inputs( - foreign_call_inputs: &[ForeignCallParam], -) -> Result, ForeignCallError> { - // Fetch the PrintableType from the foreign call input - // The remaining input values should hold what is to be printed - let (printable_type_as_values, input_values) = - foreign_call_inputs.split_last().ok_or(ForeignCallError::MissingForeignCallInputs)?; - let printable_type = fetch_printable_type(printable_type_as_values)?; - - // We must use a flat map here as each value in a struct will be in a separate input value - let mut input_values_as_fields = input_values.iter().flat_map(|param| param.fields()); - - let value = decode_value(&mut input_values_as_fields, &printable_type); - - Ok(PrintableValueDisplay::Plain(value, printable_type)) -} - -fn convert_fmt_string_inputs( - foreign_call_inputs: &[ForeignCallParam], -) -> Result, ForeignCallError> { - let (message, input_and_printable_types) = - foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?; - - let message_as_fields = message.fields(); - let message_as_string = decode_string_value(&message_as_fields); - - let (num_values, input_and_printable_types) = input_and_printable_types - .split_first() - .ok_or(ForeignCallError::MissingForeignCallInputs)?; - - let mut output = Vec::new(); - let num_values = num_values.unwrap_field().to_u128() as usize; - - let types_start_at = input_and_printable_types.len() - num_values; - let mut input_iter = - input_and_printable_types[0..types_start_at].iter().flat_map(|param| param.fields()); - for printable_type in input_and_printable_types.iter().skip(types_start_at) { - let printable_type = fetch_printable_type(printable_type)?; - let value = decode_value(&mut input_iter, &printable_type); - - output.push((value, printable_type)); - } - - Ok(PrintableValueDisplay::FmtString(message_as_string, output)) -} - -fn fetch_printable_type( - printable_type: &ForeignCallParam, -) -> Result { - let printable_type_as_fields = printable_type.fields(); - let printable_type_as_string = decode_string_value(&printable_type_as_fields); - let printable_type: PrintableType = serde_json::from_str(&printable_type_as_string)?; - - Ok(printable_type) -} - fn to_string(value: &PrintableValue, typ: &PrintableType) -> Option { let mut output = String::new(); match (value, typ) { @@ -193,7 +123,7 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Op (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Array { typ, .. }) | (PrintableValue::Vec { array_elements, is_slice }, PrintableType::Slice { typ }) => { if *is_slice { - output.push('&') + output.push('&'); } output.push('['); let mut values = array_elements.iter().peekable(); @@ -253,23 +183,6 @@ fn to_string(value: &PrintableValue, typ: &PrintableType) -> Op Some(output) } -impl std::fmt::Display for PrintableValueDisplay { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Plain(value, typ) => { - let output_string = to_string(value, typ).ok_or(std::fmt::Error)?; - write!(fmt, "{output_string}") - } - Self::FmtString(template, values) => { - let mut values_iter = values.iter(); - write_template_replacing_interpolations(template, fmt, || { - values_iter.next().and_then(|(value, typ)| to_string(value, typ)) - }) - } - } - } -} - fn write_template_replacing_interpolations( template: &str, fmt: &mut std::fmt::Formatter<'_>, @@ -346,94 +259,11 @@ fn format_field_string(field: F) -> String { "0x".to_owned() + &trimmed_field } -/// Assumes that `field_iterator` contains enough field elements in order to decode the [PrintableType] -pub fn decode_value( - field_iterator: &mut impl Iterator, - typ: &PrintableType, -) -> PrintableValue { - match typ { - PrintableType::Field - | PrintableType::SignedInteger { .. } - | PrintableType::UnsignedInteger { .. } - | PrintableType::Boolean => { - let field_element = field_iterator.next().unwrap(); - - PrintableValue::Field(field_element) - } - PrintableType::Array { length, typ } => { - let length = *length as usize; - let mut array_elements = Vec::with_capacity(length); - for _ in 0..length { - array_elements.push(decode_value(field_iterator, typ)); - } - - PrintableValue::Vec { array_elements, is_slice: false } - } - PrintableType::Slice { typ } => { - let length = field_iterator - .next() - .expect("not enough data to decode variable array length") - .to_u128() as usize; - let mut array_elements = Vec::with_capacity(length); - for _ in 0..length { - array_elements.push(decode_value(field_iterator, typ)); - } - - PrintableValue::Vec { array_elements, is_slice: true } - } - PrintableType::Tuple { types } => PrintableValue::Vec { - array_elements: vecmap(types, |typ| decode_value(field_iterator, typ)), - is_slice: false, - }, - PrintableType::String { length } => { - let field_elements: Vec = field_iterator.take(*length as usize).collect(); - - PrintableValue::String(decode_string_value(&field_elements)) - } - PrintableType::Struct { fields, .. } => { - let mut struct_map = BTreeMap::new(); - - for (field_key, param_type) in fields { - let field_value = decode_value(field_iterator, param_type); - - struct_map.insert(field_key.to_owned(), field_value); - } - - PrintableValue::Struct(struct_map) - } - PrintableType::Function { env, .. } => { - let field_element = field_iterator.next().unwrap(); - let func_ref = PrintableValue::Field(field_element); - // we want to consume the fields from the environment, but for now they are not actually printed - decode_value(field_iterator, env); - func_ref - } - PrintableType::MutableReference { typ } => { - // we decode the reference, but it's not really used for printing - decode_value(field_iterator, typ) - } - PrintableType::Unit => PrintableValue::Field(F::zero()), - } -} - -pub fn decode_string_value(field_elements: &[F]) -> String { - // TODO: Replace with `into` when Char is supported - let string_as_slice = vecmap(field_elements, |e| { - let mut field_as_bytes = e.to_be_bytes(); - let char_byte = field_as_bytes.pop().unwrap(); // A character in a string is represented by a u8, thus we just want the last byte of the element - assert!(field_as_bytes.into_iter().all(|b| b == 0)); // Assert that the rest of the field element's bytes are empty - char_byte - }); - - let final_string = str::from_utf8(&string_as_slice).unwrap(); - final_string.to_owned() -} - #[cfg(test)] mod tests { use acvm::FieldElement; - use crate::{PrintableType, PrintableValue, PrintableValueDisplay}; + use super::{PrintableType, PrintableValue, PrintableValueDisplay}; #[test] fn printable_value_display_to_string_without_interpolations() { diff --git a/noir/noir-repo/compiler/wasm/Cargo.toml b/noir/noir-repo/compiler/wasm/Cargo.toml index 9951b23f609..5cde0dfbbcf 100644 --- a/noir/noir-repo/compiler/wasm/Cargo.toml +++ b/noir/noir-repo/compiler/wasm/Cargo.toml @@ -17,9 +17,9 @@ workspace = true crate-type = ["cdylib"] [dependencies] + acvm = { workspace = true, features = ["bn254"] } fm.workspace = true -nargo.workspace = true noirc_driver.workspace = true noirc_frontend = { workspace = true, features = ["bn254"] } noirc_errors.workspace = true @@ -33,6 +33,10 @@ gloo-utils.workspace = true tracing-subscriber.workspace = true tracing-web.workspace = true +# Cannot use the `rpc` feature because the HTTP dependency wouldn't compile to Wasm. +# We could use `path` if `rpc` was a default feature, but we made it opt-in so we don't get any problems when publishing the workspace. +nargo.workspace = true + # This is an unused dependency, we are adding it # so that we can enable the js feature in getrandom. getrandom = { workspace = true, features = ["js"] } diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 826e30fa86a..ed9f7427c6f 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -126,6 +126,7 @@ "jmpifs", "jmps", "jsdoc", + "jsonrpsee", "Jubjub", "keccak", "keccakf", @@ -166,6 +167,7 @@ "nomicfoundation", "noncanonical", "nouner", + "oneshot", "overflowing", "pedersen", "peekable", diff --git a/noir/noir-repo/deny.toml b/noir/noir-repo/deny.toml index 661c8095281..48628fb0045 100644 --- a/noir/noir-repo/deny.toml +++ b/noir/noir-repo/deny.toml @@ -66,14 +66,19 @@ exceptions = [ # so we prefer to not have dependencies using it # https://tldrlegal.com/license/creative-commons-cc0-1.0-universal { allow = ["CC0-1.0"], name = "more-asserts" }, - { allow = ["CC0-1.0"], name = "jsonrpc" }, { allow = ["CC0-1.0"], name = "notify" }, { allow = ["CC0-1.0"], name = "tiny-keccak" }, { allow = ["MPL-2.0"], name = "sized-chunks" }, { allow = ["MPL-2.0"], name = "webpki-roots" }, { allow = ["CDDL-1.0"], name = "inferno" }, + { allow = ["OpenSSL"], name = "ring" }, ] +[[licenses.clarify]] +crate = "ring" +expression = "ISC" +license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] + # This section is considered when running `cargo deny check sources`. # More documentation about the 'sources' section can be found here: # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html diff --git a/noir/noir-repo/docs/docs/explainers/explainer-writing-noir.md b/noir/noir-repo/docs/docs/explainers/explainer-writing-noir.md index 3ce4245dc45..202bf76a827 100644 --- a/noir/noir-repo/docs/docs/explainers/explainer-writing-noir.md +++ b/noir/noir-repo/docs/docs/explainers/explainer-writing-noir.md @@ -140,6 +140,18 @@ Use arrays and indices that are known at compile time where possible. Using `assert_constant(i);` before an index, `i`, is used in an array will give a compile error if `i` is NOT known at compile time. ::: +### Reduce what is inside loops and conditional logic + +Putting less logic inside an `if` (`else`, etc) paths, or inside a loop, translates to less gates required to represent the program. The compiler should mostly take care of this. + +A loop duplicates the gates for each iteration of the loop, or put another way, "unrolls" the loop. Any calculations/calls that are unchanged in the loop should be calculated once before, and the result used in the loop. + +An `if` statement is "flattened" and gates created for each path even if execution uses only one path. Furthermore, there are additional operations required for each path. Sometimes this can have a multiplying effect on the operations in the `if` and `else` etc. + +:::tip +Only have essential computation inside conditional logic and loops, and calculate anything else once (before, or after, depending). +::: + ### Leverage unconstrained execution Constrained verification can leverage unconstrained execution, this is especially useful for operations that are represented by many gates. diff --git a/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md index 1fdee42425e..b2257e8bdbb 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/docs/noir/concepts/data_types/strings.md @@ -77,3 +77,38 @@ let s = r#"Simon says "hello world""#; // Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; ``` + +## Format strings + +A format string begins with the letter `f` and allows inserting the value of local and global variables in it. + +Example: + +```rust +let four = 2 + 2; +let s = f"Two plus two is: {four}"; +println(s); +``` + +The output of the above program is: + +```text +Two plus two is: 4 +``` + +To insert the value of a local or global variable, put it inside `{...}` in the string. + +If you need to write the `{` or `}` characters, use `{{` and `}}` respectively: + +```rust +let four = 2 + 2; + +// Prints "This is not expanded: {four}" +println(f"This is not expanded: {{four}}"); +``` + +More complex expressions are not allowed inside `{...}`: + +```rust +let s = f"Two plus two is: {2 + 2}" // Error: invalid format string +``` \ No newline at end of file diff --git a/noir/noir-repo/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/strings.md b/noir/noir-repo/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/strings.md index 1fdee42425e..b2257e8bdbb 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/strings.md +++ b/noir/noir-repo/docs/versioned_docs/version-v1.0.0-beta.1/noir/concepts/data_types/strings.md @@ -77,3 +77,38 @@ let s = r#"Simon says "hello world""#; // Any number of hashes may be used (>= 1) as long as the string also terminates with the same number of hashes let s = r#####"One "#, Two "##, Three "###, Four "####, Five will end the string."#####; ``` + +## Format strings + +A format string begins with the letter `f` and allows inserting the value of local and global variables in it. + +Example: + +```rust +let four = 2 + 2; +let s = f"Two plus two is: {four}"; +println(s); +``` + +The output of the above program is: + +```text +Two plus two is: 4 +``` + +To insert the value of a local or global variable, put it inside `{...}` in the string. + +If you need to write the `{` or `}` characters, use `{{` and `}}` respectively: + +```rust +let four = 2 + 2; + +// Prints "This is not expanded: {four}" +println(f"This is not expanded: {{four}}"); +``` + +More complex expressions are not allowed inside `{...}`: + +```rust +let s = f"Two plus two is: {2 + 2}" // Error: invalid format string +``` \ No newline at end of file diff --git a/noir/noir-repo/test_programs/memory_report.sh b/noir/noir-repo/test_programs/memory_report.sh index 4d03726d374..e501464c198 100755 --- a/noir/noir-repo/test_programs/memory_report.sh +++ b/noir/noir-repo/test_programs/memory_report.sh @@ -12,7 +12,7 @@ current_dir=$(pwd) base_path="$current_dir/execution_success" # If there is an argument that means we want to generate a report for only the current directory -if [ "$#" -ne 0 ]; then +if [ "$1" == "1" ]; then base_path="$current_dir" tests_to_profile=(".") fi @@ -31,11 +31,16 @@ for test_name in ${tests_to_profile[@]}; do echo " ," >> $current_dir"/memory_report.json" fi - if [ "$#" -ne 0 ]; then + if [ "$1" == "1" ]; then test_name=$(basename $current_dir) fi - heaptrack --output $current_dir/$test_name"_heap" $NARGO compile --force + COMMAND="compile --force --silence-warnings" + if [ "$2" == "1" ]; then + COMMAND="execute --silence-warnings" + fi + + heaptrack --output $current_dir/$test_name"_heap" $NARGO $COMMAND if test -f $current_dir/$test_name"_heap.gz"; then heaptrack --analyze $current_dir/$test_name"_heap.gz" > $current_dir/$test_name"_heap_analysis.txt" diff --git a/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs index d4473eb3eef..c3c83a8f000 100644 --- a/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/acvm_cli/src/cli/execute_cmd.rs @@ -9,7 +9,7 @@ use nargo::PrintOutput; use crate::cli::fs::inputs::{read_bytecode_from_file, read_inputs_from_file}; use crate::errors::CliError; -use nargo::{foreign_calls::DefaultForeignCallExecutor, ops::execute_program}; +use nargo::{foreign_calls::DefaultForeignCallBuilder, ops::execute_program}; use super::fs::witness::{create_output_witness_string, save_witness_to_dir}; @@ -74,7 +74,8 @@ pub(crate) fn execute_program_from_witness( &program, inputs_map, &Bn254BlackBoxSolver, - &mut DefaultForeignCallExecutor::new(PrintOutput::Stdout, None, None, None), + &mut DefaultForeignCallBuilder { output: PrintOutput::Stdout, ..Default::default() } + .build(), ) .map_err(CliError::CircuitExecutionError) } diff --git a/noir/noir-repo/tooling/debugger/src/foreign_calls.rs b/noir/noir-repo/tooling/debugger/src/foreign_calls.rs index 899ba892d8f..b92e22844ea 100644 --- a/noir/noir-repo/tooling/debugger/src/foreign_calls.rs +++ b/noir/noir-repo/tooling/debugger/src/foreign_calls.rs @@ -4,12 +4,13 @@ use acvm::{ AcirField, FieldElement, }; use nargo::{ - foreign_calls::{DefaultForeignCallExecutor, ForeignCallExecutor}, + foreign_calls::{ + layers::Layer, DefaultForeignCallBuilder, ForeignCallError, ForeignCallExecutor, + }, PrintOutput, }; use noirc_artifacts::debug::{DebugArtifact, DebugVars, StackFrame}; use noirc_errors::debug_info::{DebugFnId, DebugVarId}; -use noirc_printable_type::ForeignCallError; pub(crate) enum DebugForeignCall { VarAssign, @@ -44,23 +45,31 @@ pub trait DebugForeignCallExecutor: ForeignCallExecutor { fn current_stack_frame(&self) -> Option>; } -pub struct DefaultDebugForeignCallExecutor<'a> { - executor: DefaultForeignCallExecutor<'a, FieldElement>, +#[derive(Default)] +pub struct DefaultDebugForeignCallExecutor { pub debug_vars: DebugVars, } -impl<'a> DefaultDebugForeignCallExecutor<'a> { - pub fn new(output: PrintOutput<'a>) -> Self { - Self { - executor: DefaultForeignCallExecutor::new(output, None, None, None), - debug_vars: DebugVars::default(), - } +impl DefaultDebugForeignCallExecutor { + fn make( + output: PrintOutput<'_>, + ex: DefaultDebugForeignCallExecutor, + ) -> impl DebugForeignCallExecutor + '_ { + DefaultForeignCallBuilder::default().with_output(output).build().add_layer(ex) + } + + #[allow(clippy::new_ret_no_self, dead_code)] + pub fn new(output: PrintOutput<'_>) -> impl DebugForeignCallExecutor + '_ { + Self::make(output, Self::default()) } - pub fn from_artifact(output: PrintOutput<'a>, artifact: &DebugArtifact) -> Self { - let mut ex = Self::new(output); + pub fn from_artifact<'a>( + output: PrintOutput<'a>, + artifact: &DebugArtifact, + ) -> impl DebugForeignCallExecutor + 'a { + let mut ex = Self::default(); ex.load_artifact(artifact); - ex + Self::make(output, ex) } pub fn load_artifact(&mut self, artifact: &DebugArtifact) { @@ -73,7 +82,7 @@ impl<'a> DefaultDebugForeignCallExecutor<'a> { } } -impl DebugForeignCallExecutor for DefaultDebugForeignCallExecutor<'_> { +impl DebugForeignCallExecutor for DefaultDebugForeignCallExecutor { fn get_variables(&self) -> Vec> { self.debug_vars.get_variables() } @@ -91,7 +100,7 @@ fn debug_fn_id(value: &FieldElement) -> DebugFnId { DebugFnId(value.to_u128() as u32) } -impl ForeignCallExecutor for DefaultDebugForeignCallExecutor<'_> { +impl ForeignCallExecutor for DefaultDebugForeignCallExecutor { fn execute( &mut self, foreign_call: &ForeignCallWaitInfo, @@ -166,7 +175,21 @@ impl ForeignCallExecutor for DefaultDebugForeignCallExecutor<'_> { self.debug_vars.pop_fn(); Ok(ForeignCallResult::default()) } - None => self.executor.execute(foreign_call), + None => Err(ForeignCallError::NoHandler(foreign_call_name.to_string())), } } } + +impl DebugForeignCallExecutor for Layer +where + H: DebugForeignCallExecutor, + I: ForeignCallExecutor, +{ + fn get_variables(&self) -> Vec> { + self.handler().get_variables() + } + + fn current_stack_frame(&self) -> Option> { + self.handler().current_stack_frame() + } +} diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion.rs b/noir/noir-repo/tooling/lsp/src/requests/completion.rs index 3762ba9cf8d..fd6ef60af82 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion.rs @@ -31,7 +31,7 @@ use noirc_frontend::{ }, }, hir_def::traits::Trait, - node_interner::{NodeInterner, ReferenceId, StructId}, + node_interner::{FuncId, NodeInterner, ReferenceId, StructId}, parser::{Item, ItemKind, ParsedSubModule}, token::{MetaAttribute, Token, Tokens}, Kind, ParsedModule, StructType, Type, TypeBinding, @@ -120,6 +120,8 @@ struct NodeFinder<'a> { use_segment_positions: UseSegmentPositions, self_type: Option, in_comptime: bool, + /// The function we are in, if any + func_id: Option, } impl<'a> NodeFinder<'a> { @@ -165,6 +167,7 @@ impl<'a> NodeFinder<'a> { use_segment_positions: UseSegmentPositions::default(), self_type: None, in_comptime: false, + func_id: None, } } @@ -639,6 +642,13 @@ impl<'a> NodeFinder<'a> { function_completion_kind: FunctionCompletionKind, self_prefix: bool, ) { + self.complete_trait_constraints_methods( + typ, + prefix, + function_kind, + function_completion_kind, + ); + let Some(methods_by_name) = self.interner.get_type_methods(typ) else { return; }; @@ -697,6 +707,31 @@ impl<'a> NodeFinder<'a> { } } + fn complete_trait_constraints_methods( + &mut self, + typ: &Type, + prefix: &str, + function_kind: FunctionKind, + function_completion_kind: FunctionCompletionKind, + ) { + let Some(func_id) = self.func_id else { + return; + }; + + let func_meta = self.interner.function_meta(&func_id); + for constraint in &func_meta.trait_constraints { + if *typ == constraint.typ { + let trait_ = self.interner.get_trait(constraint.trait_bound.trait_id); + self.complete_trait_methods( + trait_, + prefix, + function_kind, + function_completion_kind, + ); + } + } + } + fn complete_trait_methods( &mut self, trait_: &Trait, @@ -1125,8 +1160,17 @@ impl<'a> Visitor for NodeFinder<'a> { let old_in_comptime = self.in_comptime; self.in_comptime = noir_function.def.is_comptime; + if let Some(ReferenceId::Function(func_id)) = self + .interner + .reference_at_location(Location::new(noir_function.name_ident().span(), self.file)) + { + self.func_id = Some(func_id); + } + noir_function.def.body.accept(Some(span), self); + self.func_id = None; + self.in_comptime = old_in_comptime; self.type_parameters = old_type_parameters; self.self_type = None; @@ -1207,7 +1251,7 @@ impl<'a> Visitor for NodeFinder<'a> { fn visit_trait_item_function( &mut self, - _name: &Ident, + name: &Ident, generics: &UnresolvedGenerics, parameters: &[(Ident, UnresolvedType)], return_type: &noirc_frontend::ast::FunctionReturnType, @@ -1232,7 +1276,16 @@ impl<'a> Visitor for NodeFinder<'a> { for (name, _) in parameters { self.local_variables.insert(name.to_string(), name.span()); } + + if let Some(ReferenceId::Function(func_id)) = + self.interner.reference_at_location(Location::new(name.span(), self.file)) + { + self.func_id = Some(func_id); + } + body.accept(None, self); + + self.func_id = None; }; self.type_parameters = old_type_parameters; diff --git a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs index 97c7ad86d5a..65157090767 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/completion/tests.rs @@ -2861,4 +2861,22 @@ fn main() { assert_eq!(items.len(), 1); assert!(items[0].label == "bar_baz()"); } + + #[test] + async fn test_suggests_trait_method_from_where_clause_in_function() { + let src = r#" + trait Foo { + fn foo(self) -> i32; + } + + fn something(x: T) -> i32 + where + T: Foo, + { + x.fo>|< + } + "#; + let items = get_completions(src).await; + assert_eq!(items.len(), 1); + } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/mod.rs b/noir/noir-repo/tooling/lsp/src/requests/mod.rs index 22bdda8d7d7..f7b58d7d42f 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/mod.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/mod.rs @@ -18,6 +18,7 @@ use nargo_fmt::Config; use noirc_frontend::graph::CrateId; use noirc_frontend::hir::def_map::CrateDefMap; +use noirc_frontend::parser::ParserError; use noirc_frontend::usage_tracker::UsageTracker; use noirc_frontend::{graph::Dependency, node_interner::NodeInterner}; use serde::{Deserialize, Serialize}; @@ -285,7 +286,8 @@ fn on_formatting_inner( if let Some(source) = state.input_files.get(&path) { let (module, errors) = noirc_frontend::parse_program(source); - if !errors.is_empty() { + let is_all_warnings = errors.iter().all(ParserError::is_warning); + if !is_all_warnings { return Ok(None); } diff --git a/noir/noir-repo/tooling/lsp/src/requests/test_run.rs b/noir/noir-repo/tooling/lsp/src/requests/test_run.rs index 72ae6695b82..1071866dfad 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/test_run.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/test_run.rs @@ -3,6 +3,7 @@ use std::future::{self, Future}; use crate::insert_all_files_for_workspace_into_file_manager; use async_lsp::{ErrorCode, ResponseError}; use nargo::{ + foreign_calls::DefaultForeignCallBuilder, ops::{run_test, TestStatus}, PrintOutput, }; @@ -88,10 +89,16 @@ fn on_test_run_request_inner( &mut context, &test_function, PrintOutput::Stdout, - None, - Some(workspace.root_dir.clone()), - Some(package.name.to_string()), &CompileOptions::default(), + |output, base| { + DefaultForeignCallBuilder { + output, + resolver_url: None, // NB without this the root and package don't do anything. + root_path: Some(workspace.root_dir.clone()), + package_name: Some(package.name.to_string()), + } + .build_with_base(base) + }, ); let result = match test_result { TestStatus::Pass => NargoTestRunResult { diff --git a/noir/noir-repo/tooling/nargo/Cargo.toml b/noir/noir-repo/tooling/nargo/Cargo.toml index 1dbb9978b0b..9fb46b78bc9 100644 --- a/noir/noir-repo/tooling/nargo/Cargo.toml +++ b/noir/noir-repo/tooling/nargo/Cargo.toml @@ -21,20 +21,27 @@ noirc_errors.workspace = true noirc_frontend.workspace = true noirc_printable_type.workspace = true iter-extended.workspace = true +jsonrpsee.workspace = true +rayon.workspace = true thiserror.workspace = true tracing.workspace = true -rayon.workspace = true -jsonrpc.workspace = true -rand.workspace = true serde.workspace = true +serde_json.workspace = true walkdir = "2.5.0" +# Some dependencies are optional so we can compile to Wasm. +tokio = { workspace = true, optional = true } +rand = { workspace = true, optional = true } + [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -noir_fuzzer.workspace = true -proptest.workspace = true +noir_fuzzer = { workspace = true } +proptest = { workspace = true } [dev-dependencies] -jsonrpc-http-server = "18.0" -jsonrpc-core-client = "18.0" -jsonrpc-derive = "18.0" -jsonrpc-core = "18.0" +jsonrpsee = { workspace = true, features = ["server"] } + +[features] +default = [] + +# Execution currently uses HTTP based Oracle resolvers; does not compile to Wasm. +rpc = ["jsonrpsee/http-client", "jsonrpsee/macros", "tokio/rt", "rand"] diff --git a/noir/noir-repo/tooling/nargo/src/errors.rs b/noir/noir-repo/tooling/nargo/src/errors.rs index 5256f28e36c..00c411bf7e4 100644 --- a/noir/noir-repo/tooling/nargo/src/errors.rs +++ b/noir/noir-repo/tooling/nargo/src/errors.rs @@ -16,9 +16,10 @@ use noirc_errors::{ pub use noirc_errors::Location; use noirc_driver::CrateName; -use noirc_printable_type::ForeignCallError; use thiserror::Error; +use crate::foreign_calls::ForeignCallError; + /// Errors covering situations where a package cannot be compiled. #[derive(Debug, Error)] pub enum CompileError { diff --git a/noir/noir-repo/tooling/nargo/src/foreign_calls/default.rs b/noir/noir-repo/tooling/nargo/src/foreign_calls/default.rs new file mode 100644 index 00000000000..ce4af3aa744 --- /dev/null +++ b/noir/noir-repo/tooling/nargo/src/foreign_calls/default.rs @@ -0,0 +1,115 @@ +use acvm::AcirField; +use serde::{Deserialize, Serialize}; + +use crate::PrintOutput; + +use super::{ + layers::{self, Layer, Layering}, + mocker::MockForeignCallExecutor, + print::PrintForeignCallExecutor, + ForeignCallExecutor, +}; + +#[cfg(feature = "rpc")] +use super::rpc::RPCForeignCallExecutor; + +/// A builder for [DefaultForeignCallLayers] where we can enable fields based on feature flags, +/// which is easier than providing different overrides for a `new` method. +#[derive(Default)] +pub struct DefaultForeignCallBuilder<'a> { + pub output: PrintOutput<'a>, + #[cfg(feature = "rpc")] + pub resolver_url: Option, + #[cfg(feature = "rpc")] + pub root_path: Option, + #[cfg(feature = "rpc")] + pub package_name: Option, +} + +impl<'a> DefaultForeignCallBuilder<'a> { + /// Override the output. + pub fn with_output(mut self, output: PrintOutput<'a>) -> Self { + self.output = output; + self + } + + /// Compose the executor layers with [layers::Empty] as the default handler. + pub fn build(self) -> DefaultForeignCallLayers<'a, layers::Empty, F> + where + F: AcirField + Serialize + for<'de> Deserialize<'de> + 'a, + { + self.build_with_base(layers::Empty) + } + + /// Compose the executor layers with `base` as the default handler. + pub fn build_with_base(self, base: B) -> DefaultForeignCallLayers<'a, B, F> + where + F: AcirField + Serialize + for<'de> Deserialize<'de> + 'a, + B: ForeignCallExecutor + 'a, + { + let executor = { + #[cfg(feature = "rpc")] + { + use rand::Rng; + + base.add_layer(self.resolver_url.map(|resolver_url| { + let id = rand::thread_rng().gen(); + RPCForeignCallExecutor::new( + &resolver_url, + id, + self.root_path, + self.package_name, + ) + })) + } + #[cfg(not(feature = "rpc"))] + { + base + } + }; + + executor + .add_layer(MockForeignCallExecutor::default()) + .add_layer(PrintForeignCallExecutor::new(self.output)) + } +} + +/// Facilitate static typing of layers on a base layer, so inner layers can be accessed. +#[cfg(feature = "rpc")] +pub type DefaultForeignCallLayers<'a, B, F> = Layer< + PrintForeignCallExecutor<'a>, + Layer, Layer, B>>, +>; +#[cfg(not(feature = "rpc"))] +pub type DefaultForeignCallLayers<'a, B, F> = + Layer, Layer, B>>; + +/// Convenience constructor for code that used to create the executor this way. +#[cfg(feature = "rpc")] +pub struct DefaultForeignCallExecutor; + +/// Convenience constructors for the RPC case. Non-RPC versions are not provided +/// because once a crate opts into this within the workspace, everyone gets it +/// even if they don't want to. For the non-RPC case we can nudge people to +/// use `DefaultForeignCallBuilder` which is easier to keep flexible. +#[cfg(feature = "rpc")] +impl DefaultForeignCallExecutor { + #[allow(clippy::new_ret_no_self)] + pub fn new<'a, F>( + output: PrintOutput<'a>, + resolver_url: Option<&str>, + root_path: Option, + package_name: Option, + ) -> impl ForeignCallExecutor + 'a + where + F: AcirField + Serialize + for<'de> Deserialize<'de> + 'a, + { + DefaultForeignCallBuilder { + output, + resolver_url: resolver_url.map(|s| s.to_string()), + root_path, + package_name, + } + .build() + } +} diff --git a/noir/noir-repo/tooling/nargo/src/foreign_calls/layers.rs b/noir/noir-repo/tooling/nargo/src/foreign_calls/layers.rs new file mode 100644 index 00000000000..19f14c6f4a8 --- /dev/null +++ b/noir/noir-repo/tooling/nargo/src/foreign_calls/layers.rs @@ -0,0 +1,140 @@ +use acvm::{acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, AcirField}; + +use super::{ForeignCallError, ForeignCallExecutor}; + +/// Returns an empty result when called. +/// +/// If all executors have no handler for the given foreign call then we cannot +/// return a correct response to the ACVM. The best we can do is to return an empty response, +/// this allows us to ignore any foreign calls which exist solely to pass information from inside +/// the circuit to the environment (e.g. custom logging) as the execution will still be able to progress. +/// +/// We optimistically return an empty response for all oracle calls as the ACVM will error +/// should a response have been required. +pub struct Empty; + +impl ForeignCallExecutor for Empty { + fn execute( + &mut self, + _foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + Ok(ForeignCallResult::default()) + } +} + +/// Returns `NoHandler` for every call. +pub struct Unhandled; + +impl ForeignCallExecutor for Unhandled { + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + Err(ForeignCallError::NoHandler(foreign_call.function.clone())) + } +} + +/// Forwards to the inner executor if its own handler doesn't handle the call. +pub struct Layer { + pub handler: H, + pub inner: I, +} + +impl ForeignCallExecutor for Layer +where + H: ForeignCallExecutor, + I: ForeignCallExecutor, +{ + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + match self.handler.execute(foreign_call) { + Err(ForeignCallError::NoHandler(_)) => self.inner.execute(foreign_call), + handled => handled, + } + } +} + +impl Layer { + /// Create a layer from two handlers + pub fn new(handler: H, inner: I) -> Self { + Self { handler, inner } + } +} + +impl Layer { + /// Create a layer from a handler. + /// If the handler doesn't handle a call, a default empty response is returned. + pub fn or_empty(handler: H) -> Self { + Self { handler, inner: Empty } + } +} + +impl Layer { + /// Create a layer from a handler. + /// If the handler doesn't handle a call, `NoHandler` error is returned. + pub fn or_unhandled(handler: H) -> Self { + Self { handler, inner: Unhandled } + } +} + +impl Layer { + /// A base layer that doesn't handle anything. + pub fn unhandled() -> Self { + Self { handler: Unhandled, inner: Unhandled } + } +} + +impl Layer { + /// Add another layer on top of this one. + pub fn add_layer(self, handler: J) -> Layer { + Layer::new(handler, self) + } + + pub fn handler(&self) -> &H { + &self.handler + } + + pub fn inner(&self) -> &I { + &self.inner + } +} + +/// Compose handlers. +pub trait Layering { + /// Layer an executor on top of this one. + /// The `other` executor will be called first. + fn add_layer(self, other: L) -> Layer + where + Self: Sized + ForeignCallExecutor, + L: ForeignCallExecutor; +} + +impl Layering for T { + fn add_layer(self, other: L) -> Layer + where + T: Sized + ForeignCallExecutor, + L: ForeignCallExecutor, + { + Layer::new(other, self) + } +} + +/// Support disabling a layer by making it optional. +/// This way we can still have a known static type for a composition, +/// because layers are always added, potentially wrapped in an `Option`. +impl ForeignCallExecutor for Option +where + H: ForeignCallExecutor, +{ + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + match self { + Some(handler) => handler.execute(foreign_call), + None => Err(ForeignCallError::NoHandler(foreign_call.function.clone())), + } + } +} diff --git a/noir/noir-repo/tooling/nargo/src/foreign_calls/mocker.rs b/noir/noir-repo/tooling/nargo/src/foreign_calls/mocker.rs index c93d16bbaf6..b289e907cd7 100644 --- a/noir/noir-repo/tooling/nargo/src/foreign_calls/mocker.rs +++ b/noir/noir-repo/tooling/nargo/src/foreign_calls/mocker.rs @@ -1,12 +1,13 @@ +use std::marker::PhantomData; + use acvm::{ acir::brillig::{ForeignCallParam, ForeignCallResult}, pwg::ForeignCallWaitInfo, AcirField, }; -use noirc_printable_type::{decode_string_value, ForeignCallError}; -use serde::{Deserialize, Serialize}; +use noirc_abi::decode_string_value; -use super::{ForeignCall, ForeignCallExecutor}; +use super::{ForeignCall, ForeignCallError, ForeignCallExecutor}; /// This struct represents an oracle mock. It can be used for testing programs that use oracles. #[derive(Debug, PartialEq, Eq, Clone)] @@ -45,7 +46,7 @@ impl MockedCall { } #[derive(Debug, Default)] -pub(crate) struct MockForeignCallExecutor { +pub struct MockForeignCallExecutor { /// Mocks have unique ids used to identify them in Noir, allowing to update or remove them. last_mock_id: usize, /// The registered mocks @@ -78,8 +79,9 @@ impl MockForeignCallExecutor { } } -impl Deserialize<'a>> ForeignCallExecutor - for MockForeignCallExecutor +impl ForeignCallExecutor for MockForeignCallExecutor +where + F: AcirField, { fn execute( &mut self, @@ -174,3 +176,30 @@ impl Deserialize<'a>> ForeignCallExecutor } } } + +/// Handler that panics if any of the mock functions are called. +#[allow(dead_code)] // TODO: Make the mocker optional +pub(crate) struct DisabledMockForeignCallExecutor { + _field: PhantomData, +} + +impl ForeignCallExecutor for DisabledMockForeignCallExecutor { + fn execute( + &mut self, + foreign_call: &ForeignCallWaitInfo, + ) -> Result, ForeignCallError> { + let foreign_call_name = foreign_call.function.as_str(); + if let Some( + ForeignCall::CreateMock + | ForeignCall::SetMockParams + | ForeignCall::GetMockLastParams + | ForeignCall::SetMockReturns + | ForeignCall::SetMockTimes + | ForeignCall::ClearMock, + ) = ForeignCall::lookup(foreign_call_name) + { + panic!("unexpected mock call: {}", foreign_call.function) + } + Err(ForeignCallError::NoHandler(foreign_call.function.clone())) + } +} diff --git a/noir/noir-repo/tooling/nargo/src/foreign_calls/mod.rs b/noir/noir-repo/tooling/nargo/src/foreign_calls/mod.rs index 65ff051bcbf..06fe42bfec9 100644 --- a/noir/noir-repo/tooling/nargo/src/foreign_calls/mod.rs +++ b/noir/noir-repo/tooling/nargo/src/foreign_calls/mod.rs @@ -1,16 +1,16 @@ -use std::path::PathBuf; +use acvm::{acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo}; +use thiserror::Error; -use acvm::{acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, AcirField}; -use mocker::MockForeignCallExecutor; -use noirc_printable_type::ForeignCallError; -use print::{PrintForeignCallExecutor, PrintOutput}; -use rand::Rng; -use rpc::RPCForeignCallExecutor; -use serde::{Deserialize, Serialize}; +pub mod layers; +pub mod mocker; +pub mod print; -pub(crate) mod mocker; -pub(crate) mod print; -pub(crate) mod rpc; +pub mod default; +#[cfg(feature = "rpc")] +pub mod rpc; +pub use default::DefaultForeignCallBuilder; +#[cfg(feature = "rpc")] +pub use default::DefaultForeignCallExecutor; pub trait ForeignCallExecutor { fn execute( @@ -64,77 +64,20 @@ impl ForeignCall { } } -#[derive(Debug, Default)] -pub struct DefaultForeignCallExecutor<'a, F> { - /// The executor for any [`ForeignCall::Print`] calls. - printer: PrintForeignCallExecutor<'a>, - mocker: MockForeignCallExecutor, - external: Option, -} - -impl<'a, F: Default> DefaultForeignCallExecutor<'a, F> { - pub fn new( - output: PrintOutput<'a>, - resolver_url: Option<&str>, - root_path: Option, - package_name: Option, - ) -> Self { - let id = rand::thread_rng().gen(); - let printer = PrintForeignCallExecutor { output }; - let external_resolver = resolver_url.map(|resolver_url| { - RPCForeignCallExecutor::new(resolver_url, id, root_path, package_name) - }); - DefaultForeignCallExecutor { - printer, - mocker: MockForeignCallExecutor::default(), - external: external_resolver, - } - } -} +#[derive(Debug, Error)] +pub enum ForeignCallError { + #[error("No handler could be found for foreign call `{0}`")] + NoHandler(String), -impl<'a, F: AcirField + Serialize + for<'b> Deserialize<'b>> ForeignCallExecutor - for DefaultForeignCallExecutor<'a, F> -{ - fn execute( - &mut self, - foreign_call: &ForeignCallWaitInfo, - ) -> Result, ForeignCallError> { - let foreign_call_name = foreign_call.function.as_str(); - match ForeignCall::lookup(foreign_call_name) { - Some(ForeignCall::Print) => self.printer.execute(foreign_call), - Some( - ForeignCall::CreateMock - | ForeignCall::SetMockParams - | ForeignCall::GetMockLastParams - | ForeignCall::SetMockReturns - | ForeignCall::SetMockTimes - | ForeignCall::ClearMock, - ) => self.mocker.execute(foreign_call), + #[error("Foreign call inputs needed for execution are missing")] + MissingForeignCallInputs, - None => { - // First check if there's any defined mock responses for this foreign call. - match self.mocker.execute(foreign_call) { - Err(ForeignCallError::NoHandler(_)) => (), - response_or_error => return response_or_error, - }; + #[error("Could not parse PrintableType argument. {0}")] + ParsingError(#[from] serde_json::Error), - if let Some(external_resolver) = &mut self.external { - // If the user has registered an external resolver then we forward any remaining oracle calls there. - match external_resolver.execute(foreign_call) { - Err(ForeignCallError::NoHandler(_)) => (), - response_or_error => return response_or_error, - }; - } + #[error("Failed calling external resolver. {0}")] + ExternalResolverError(#[from] jsonrpsee::core::client::Error), - // If all executors have no handler for the given foreign call then we cannot - // return a correct response to the ACVM. The best we can do is to return an empty response, - // this allows us to ignore any foreign calls which exist solely to pass information from inside - // the circuit to the environment (e.g. custom logging) as the execution will still be able to progress. - // - // We optimistically return an empty response for all oracle calls as the ACVM will error - // should a response have been required. - Ok(ForeignCallResult::default()) - } - } - } + #[error("Assert message resolved after an unsatisfied constrain. {0}")] + ResolvedAssertMessage(String), } diff --git a/noir/noir-repo/tooling/nargo/src/foreign_calls/print.rs b/noir/noir-repo/tooling/nargo/src/foreign_calls/print.rs index 8b2b5efd8b6..fb5621da942 100644 --- a/noir/noir-repo/tooling/nargo/src/foreign_calls/print.rs +++ b/noir/noir-repo/tooling/nargo/src/foreign_calls/print.rs @@ -1,7 +1,12 @@ -use acvm::{acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, AcirField}; -use noirc_printable_type::{ForeignCallError, PrintableValueDisplay}; +use acvm::{ + acir::brillig::{ForeignCallParam, ForeignCallResult}, + pwg::ForeignCallWaitInfo, + AcirField, +}; +use noirc_abi::{decode_printable_value, decode_string_value}; +use noirc_printable_type::{PrintableType, PrintableValueDisplay}; -use super::{ForeignCall, ForeignCallExecutor}; +use super::{ForeignCall, ForeignCallError, ForeignCallExecutor}; #[derive(Debug, Default)] pub enum PrintOutput<'a> { @@ -12,8 +17,14 @@ pub enum PrintOutput<'a> { } #[derive(Debug, Default)] -pub(crate) struct PrintForeignCallExecutor<'a> { - pub(crate) output: PrintOutput<'a>, +pub struct PrintForeignCallExecutor<'a> { + output: PrintOutput<'a>, +} + +impl<'a> PrintForeignCallExecutor<'a> { + pub fn new(output: PrintOutput<'a>) -> Self { + Self { output } + } } impl ForeignCallExecutor for PrintForeignCallExecutor<'_> { @@ -32,7 +43,8 @@ impl ForeignCallExecutor for PrintForeignCallExecutor<'_> { .ok_or(ForeignCallError::MissingForeignCallInputs)? .1; - let display_values: PrintableValueDisplay = foreign_call_inputs.try_into()?; + let display_values: PrintableValueDisplay = + try_from_params(foreign_call_inputs)?; let display_string = format!("{display_values}{}", if skip_newline { "" } else { "\n" }); @@ -50,3 +62,72 @@ impl ForeignCallExecutor for PrintForeignCallExecutor<'_> { } } } + +fn try_from_params( + foreign_call_inputs: &[ForeignCallParam], +) -> Result, ForeignCallError> { + let (is_fmt_str, foreign_call_inputs) = + foreign_call_inputs.split_last().ok_or(ForeignCallError::MissingForeignCallInputs)?; + + if is_fmt_str.unwrap_field().is_one() { + convert_fmt_string_inputs(foreign_call_inputs) + } else { + convert_string_inputs(foreign_call_inputs) + } +} + +fn convert_string_inputs( + foreign_call_inputs: &[ForeignCallParam], +) -> Result, ForeignCallError> { + // Fetch the PrintableType from the foreign call input + // The remaining input values should hold what is to be printed + let (printable_type_as_values, input_values) = + foreign_call_inputs.split_last().ok_or(ForeignCallError::MissingForeignCallInputs)?; + let printable_type = fetch_printable_type(printable_type_as_values)?; + + // We must use a flat map here as each value in a struct will be in a separate input value + let mut input_values_as_fields = input_values.iter().flat_map(|param| param.fields()); + + let value = decode_printable_value(&mut input_values_as_fields, &printable_type); + + Ok(PrintableValueDisplay::Plain(value, printable_type)) +} + +fn convert_fmt_string_inputs( + foreign_call_inputs: &[ForeignCallParam], +) -> Result, ForeignCallError> { + let (message, input_and_printable_types) = + foreign_call_inputs.split_first().ok_or(ForeignCallError::MissingForeignCallInputs)?; + + let message_as_fields = message.fields(); + let message_as_string = decode_string_value(&message_as_fields); + + let (num_values, input_and_printable_types) = input_and_printable_types + .split_first() + .ok_or(ForeignCallError::MissingForeignCallInputs)?; + + let mut output = Vec::new(); + let num_values = num_values.unwrap_field().to_u128() as usize; + + let types_start_at = input_and_printable_types.len() - num_values; + let mut input_iter = + input_and_printable_types[0..types_start_at].iter().flat_map(|param| param.fields()); + for printable_type in input_and_printable_types.iter().skip(types_start_at) { + let printable_type = fetch_printable_type(printable_type)?; + let value = decode_printable_value(&mut input_iter, &printable_type); + + output.push((value, printable_type)); + } + + Ok(PrintableValueDisplay::FmtString(message_as_string, output)) +} + +fn fetch_printable_type( + printable_type: &ForeignCallParam, +) -> Result { + let printable_type_as_fields = printable_type.fields(); + let printable_type_as_string = decode_string_value(&printable_type_as_fields); + let printable_type: PrintableType = serde_json::from_str(&printable_type_as_string)?; + + Ok(printable_type) +} diff --git a/noir/noir-repo/tooling/nargo/src/foreign_calls/rpc.rs b/noir/noir-repo/tooling/nargo/src/foreign_calls/rpc.rs index 0653eb1c7e3..89a748b6c45 100644 --- a/noir/noir-repo/tooling/nargo/src/foreign_calls/rpc.rs +++ b/noir/noir-repo/tooling/nargo/src/foreign_calls/rpc.rs @@ -1,25 +1,31 @@ use std::path::PathBuf; use acvm::{acir::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, AcirField}; -use jsonrpc::{arg as build_json_rpc_arg, minreq_http::Builder, Client}; -use noirc_printable_type::ForeignCallError; +use jsonrpsee::{ + core::client::ClientT, + http_client::{HttpClient, HttpClientBuilder}, + rpc_params, +}; use serde::{Deserialize, Serialize}; -use super::ForeignCallExecutor; +use super::{ForeignCallError, ForeignCallExecutor}; #[derive(Debug)] -pub(crate) struct RPCForeignCallExecutor { +pub struct RPCForeignCallExecutor { /// A randomly generated id for this `DefaultForeignCallExecutor`. /// /// This is used so that a single `external_resolver` can distinguish between requests from multiple /// instantiations of `DefaultForeignCallExecutor`. id: u64, /// JSON RPC client to resolve foreign calls - external_resolver: Client, + external_resolver: HttpClient, /// Root path to the program or workspace in execution. root_path: Option, /// Name of the package in execution package_name: Option, + /// Runtime to execute asynchronous tasks on. + /// See [bridging](https://tokio.rs/tokio/topics/bridging). + runtime: tokio::runtime::Runtime, } #[derive(Debug, Serialize, Deserialize)] @@ -31,59 +37,76 @@ struct ResolveForeignCallRequest { /// performed in parallel. session_id: u64, - #[serde(flatten)] /// The foreign call which the external RPC server is to provide a response for. + #[serde(flatten)] function_call: ForeignCallWaitInfo, - #[serde(skip_serializing_if = "Option::is_none")] /// Root path to the program or workspace in execution. - root_path: Option, #[serde(skip_serializing_if = "Option::is_none")] + root_path: Option, + /// Name of the package in execution + #[serde(skip_serializing_if = "Option::is_none")] package_name: Option, } +type ResolveForeignCallResult = Result, ForeignCallError>; + impl RPCForeignCallExecutor { - pub(crate) fn new( + pub fn new( resolver_url: &str, id: u64, root_path: Option, package_name: Option, ) -> Self { - let mut transport_builder = - Builder::new().url(resolver_url).expect("Invalid oracle resolver URL"); + let mut client_builder = HttpClientBuilder::new(); if let Some(Ok(timeout)) = std::env::var("NARGO_FOREIGN_CALL_TIMEOUT").ok().map(|timeout| timeout.parse()) { let timeout_duration = std::time::Duration::from_millis(timeout); - transport_builder = transport_builder.timeout(timeout_duration); + client_builder = client_builder.request_timeout(timeout_duration); }; - let oracle_resolver = Client::with_transport(transport_builder.build()); - RPCForeignCallExecutor { external_resolver: oracle_resolver, id, root_path, package_name } + let oracle_resolver = + client_builder.build(resolver_url).expect("Invalid oracle resolver URL"); + + // Opcodes are executed in the `ProgramExecutor::execute_circuit` one by one in a loop, + // we don't need a concurrent thread pool. + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_time() + .enable_io() + .build() + .expect("failed to build tokio runtime"); + + RPCForeignCallExecutor { + external_resolver: oracle_resolver, + id, + root_path, + package_name, + runtime, + } } } -impl Deserialize<'a>> ForeignCallExecutor - for RPCForeignCallExecutor +impl ForeignCallExecutor for RPCForeignCallExecutor +where + F: AcirField + Serialize + for<'a> Deserialize<'a>, { - fn execute( - &mut self, - foreign_call: &ForeignCallWaitInfo, - ) -> Result, ForeignCallError> { - let encoded_params = vec![build_json_rpc_arg(ResolveForeignCallRequest { + /// Execute an async call blocking the current thread. + /// This method cannot be called from inside a `tokio` runtime, for that to work + /// we need to offload the execution into a different thread; see the tests. + fn execute(&mut self, foreign_call: &ForeignCallWaitInfo) -> ResolveForeignCallResult { + let encoded_params = rpc_params!(ResolveForeignCallRequest { session_id: self.id, function_call: foreign_call.clone(), root_path: self.root_path.clone().map(|path| path.to_str().unwrap().to_string()), package_name: self.package_name.clone(), - })]; - - let req = self.external_resolver.build_request("resolve_foreign_call", &encoded_params); - - let response = self.external_resolver.send_request(req)?; + }); - let parsed_response: ForeignCallResult = response.result()?; + let parsed_response = self.runtime.block_on(async { + self.external_resolver.request("resolve_foreign_call", encoded_params).await + })?; Ok(parsed_response) } @@ -95,20 +118,23 @@ mod tests { acir::brillig::ForeignCallParam, brillig_vm::brillig::ForeignCallResult, pwg::ForeignCallWaitInfo, FieldElement, }; - use jsonrpc_core::Result as RpcResult; - use jsonrpc_derive::rpc; - use jsonrpc_http_server::{Server, ServerBuilder}; - - use super::{ForeignCallExecutor, RPCForeignCallExecutor, ResolveForeignCallRequest}; + use jsonrpsee::proc_macros::rpc; + use jsonrpsee::server::Server; + use jsonrpsee::types::ErrorObjectOwned; + use tokio::sync::{mpsc, oneshot}; + + use super::{ + ForeignCallExecutor, RPCForeignCallExecutor, ResolveForeignCallRequest, + ResolveForeignCallResult, + }; - #[allow(unreachable_pub)] - #[rpc] - pub trait OracleResolver { - #[rpc(name = "resolve_foreign_call")] + #[rpc(server)] + trait OracleResolver { + #[method(name = "resolve_foreign_call")] fn resolve_foreign_call( &self, req: ResolveForeignCallRequest, - ) -> RpcResult>; + ) -> Result, ErrorObjectOwned>; } struct OracleResolverImpl; @@ -129,99 +155,129 @@ mod tests { } } - impl OracleResolver for OracleResolverImpl { + impl OracleResolverServer for OracleResolverImpl { fn resolve_foreign_call( &self, req: ResolveForeignCallRequest, - ) -> RpcResult> { + ) -> Result, ErrorObjectOwned> { let response = match req.function_call.function.as_str() { "sum" => self.sum(req.function_call.inputs[0].clone()), "echo" => self.echo(req.function_call.inputs[0].clone()), "id" => FieldElement::from(req.session_id as u128).into(), - _ => panic!("unexpected foreign call"), }; Ok(response) } } - fn build_oracle_server() -> (Server, String) { - let mut io = jsonrpc_core::IoHandler::new(); - io.extend_with(OracleResolverImpl.to_delegate()); + /// The test client send its request and a response channel. + type RPCForeignCallClientRequest = ( + ForeignCallWaitInfo, + oneshot::Sender>, + ); - // Choosing port 0 results in a random port being assigned. - let server = ServerBuilder::new(io) - .start_http(&"127.0.0.1:0".parse().expect("Invalid address")) - .expect("Could not start server"); + /// Async client used in the tests. + #[derive(Clone)] + struct RPCForeignCallClient { + tx: mpsc::UnboundedSender, + } + + impl RPCForeignCallExecutor { + /// Spawn and run the executor in the background until all clients are closed. + fn run(mut self) -> RPCForeignCallClient { + let (tx, mut rx) = mpsc::unbounded_channel::(); + let handle = tokio::task::spawn_blocking(move || { + while let Some((req, tx)) = rx.blocking_recv() { + let res = self.execute(&req); + let _ = tx.send(res); + } + }); + // The task will finish when the client goes out of scope. + drop(handle); + RPCForeignCallClient { tx } + } + } + + impl RPCForeignCallClient { + /// Asynchronously execute a foreign call. + async fn execute( + &self, + req: &ForeignCallWaitInfo, + ) -> ResolveForeignCallResult { + let (tx, rx) = oneshot::channel(); + self.tx.send((req.clone(), tx)).expect("failed to send to executor"); + rx.await.expect("failed to receive from executor") + } + } - let url = format!("http://{}", server.address()); - (server, url) + /// Start running the Oracle server or a random port, returning the listen URL. + async fn build_oracle_server() -> std::io::Result { + // Choosing port 0 results in a random port being assigned. + let server = Server::builder().build("127.0.0.1:0").await?; + let addr = server.local_addr()?; + let handle = server.start(OracleResolverImpl.into_rpc()); + let url = format!("http://{}", addr); + // In this test we don't care about doing shutdown so let's it run forever. + tokio::spawn(handle.stopped()); + Ok(url) } - #[test] - fn test_oracle_resolver_echo() { - let (server, url) = build_oracle_server(); + #[tokio::test] + async fn test_oracle_resolver_echo() { + let url = build_oracle_server().await.unwrap(); - let mut executor = RPCForeignCallExecutor::new(&url, 1, None, None); + let executor = RPCForeignCallExecutor::new(&url, 1, None, None).run(); let foreign_call: ForeignCallWaitInfo = ForeignCallWaitInfo { function: "echo".to_string(), inputs: vec![ForeignCallParam::Single(1_u128.into())], }; - let result = executor.execute(&foreign_call); + let result = executor.execute(&foreign_call).await; assert_eq!(result.unwrap(), ForeignCallResult { values: foreign_call.inputs }); - - server.close(); } - #[test] - fn test_oracle_resolver_sum() { - let (server, url) = build_oracle_server(); + #[tokio::test] + async fn test_oracle_resolver_sum() { + let url = build_oracle_server().await.unwrap(); - let mut executor = RPCForeignCallExecutor::new(&url, 2, None, None); + let executor = RPCForeignCallExecutor::new(&url, 2, None, None).run(); let foreign_call: ForeignCallWaitInfo = ForeignCallWaitInfo { function: "sum".to_string(), inputs: vec![ForeignCallParam::Array(vec![1_usize.into(), 2_usize.into()])], }; - let result = executor.execute(&foreign_call); + let result = executor.execute(&foreign_call).await; assert_eq!(result.unwrap(), FieldElement::from(3_usize).into()); - - server.close(); } - #[test] - fn foreign_call_executor_id_is_persistent() { - let (server, url) = build_oracle_server(); + #[tokio::test] + async fn foreign_call_executor_id_is_persistent() { + let url = build_oracle_server().await.unwrap(); - let mut executor = RPCForeignCallExecutor::new(&url, 3, None, None); + let executor = RPCForeignCallExecutor::new(&url, 3, None, None).run(); let foreign_call: ForeignCallWaitInfo = ForeignCallWaitInfo { function: "id".to_string(), inputs: Vec::new() }; - let result_1 = executor.execute(&foreign_call).unwrap(); - let result_2 = executor.execute(&foreign_call).unwrap(); + let result_1 = executor.execute(&foreign_call).await.unwrap(); + let result_2 = executor.execute(&foreign_call).await.unwrap(); assert_eq!(result_1, result_2); - - server.close(); } - #[test] - fn oracle_resolver_rpc_can_distinguish_executors() { - let (server, url) = build_oracle_server(); + #[tokio::test] + async fn oracle_resolver_rpc_can_distinguish_executors() { + let url = build_oracle_server().await.unwrap(); - let mut executor_1 = RPCForeignCallExecutor::new(&url, 4, None, None); - let mut executor_2 = RPCForeignCallExecutor::new(&url, 5, None, None); + let executor_1 = RPCForeignCallExecutor::new(&url, 4, None, None).run(); + let executor_2 = RPCForeignCallExecutor::new(&url, 5, None, None).run(); let foreign_call: ForeignCallWaitInfo = ForeignCallWaitInfo { function: "id".to_string(), inputs: Vec::new() }; - let result_1 = executor_1.execute(&foreign_call).unwrap(); - let result_2 = executor_2.execute(&foreign_call).unwrap(); + let result_1 = executor_1.execute(&foreign_call).await.unwrap(); + let result_2 = executor_2.execute(&foreign_call).await.unwrap(); assert_ne!(result_1, result_2); - - server.close(); } } diff --git a/noir/noir-repo/tooling/nargo/src/lib.rs b/noir/noir-repo/tooling/nargo/src/lib.rs index c126b6f526c..de032ca55ae 100644 --- a/noir/noir-repo/tooling/nargo/src/lib.rs +++ b/noir/noir-repo/tooling/nargo/src/lib.rs @@ -14,6 +14,9 @@ pub mod ops; pub mod package; pub mod workspace; +pub use self::errors::NargoError; +pub use self::foreign_calls::print::PrintOutput; + use std::{ collections::{BTreeMap, HashMap, HashSet}, path::PathBuf, @@ -29,9 +32,6 @@ use package::{Dependency, Package}; use rayon::prelude::*; use walkdir::WalkDir; -pub use self::errors::NargoError; -pub use self::foreign_calls::print::PrintOutput; - pub fn prepare_dependencies( context: &mut Context, parent_crate: CrateId, diff --git a/noir/noir-repo/tooling/nargo/src/ops/mod.rs b/noir/noir-repo/tooling/nargo/src/ops/mod.rs index 04efeb5a9ec..7a52a829be3 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/mod.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/mod.rs @@ -3,10 +3,10 @@ pub use self::compile::{ collect_errors, compile_contract, compile_program, compile_program_with_debug_instrumenter, compile_workspace, report_errors, }; -pub use self::execute::{execute_program, execute_program_with_profiling}; pub use self::optimize::{optimize_contract, optimize_program}; pub use self::transform::{transform_contract, transform_program}; +pub use self::execute::{execute_program, execute_program_with_profiling}; pub use self::test::{run_test, TestStatus}; mod check; diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index 1306150518d..bfd5cd3713f 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -1,5 +1,3 @@ -use std::path::PathBuf; - use acvm::{ acir::{ brillig::ForeignCallResult, @@ -12,18 +10,10 @@ use noirc_abi::Abi; use noirc_driver::{compile_no_check, CompileError, CompileOptions, DEFAULT_EXPRESSION_WIDTH}; use noirc_errors::{debug_info::DebugInfo, FileDiagnostic}; use noirc_frontend::hir::{def_map::TestFunction, Context}; -use noirc_printable_type::ForeignCallError; -use rand::Rng; -use serde::{Deserialize, Serialize}; use crate::{ errors::try_to_diagnose_runtime_error, - foreign_calls::{ - mocker::MockForeignCallExecutor, - print::{PrintForeignCallExecutor, PrintOutput}, - rpc::RPCForeignCallExecutor, - ForeignCall, ForeignCallExecutor, - }, + foreign_calls::{layers, print::PrintOutput, ForeignCallError, ForeignCallExecutor}, NargoError, }; @@ -43,17 +33,19 @@ impl TestStatus { } } -#[allow(clippy::too_many_arguments)] -pub fn run_test>( +pub fn run_test<'a, B, F, E>( blackbox_solver: &B, context: &mut Context, test_function: &TestFunction, - output: PrintOutput<'_>, - foreign_call_resolver_url: Option<&str>, - root_path: Option, - package_name: Option, + output: PrintOutput<'a>, config: &CompileOptions, -) -> TestStatus { + build_foreign_call_executor: F, +) -> TestStatus +where + B: BlackBoxFunctionSolver, + F: Fn(PrintOutput<'a>, layers::Unhandled) -> E + 'a, + E: ForeignCallExecutor, +{ let test_function_has_no_arguments = context .def_interner .function_meta(&test_function.get_id()) @@ -70,12 +62,9 @@ pub fn run_test>( if test_function_has_no_arguments { // Run the backend to ensure the PWG evaluates functions like std::hash::pedersen, // otherwise constraints involving these expressions will not error. - let mut foreign_call_executor = TestForeignCallExecutor::new( - output, - foreign_call_resolver_url, - root_path, - package_name, - ); + // Use a base layer that doesn't handle anything, which we handle in the `execute` below. + let inner_executor = build_foreign_call_executor(output, layers::Unhandled); + let mut foreign_call_executor = TestForeignCallExecutor::new(inner_executor); let circuit_execution = execute_program( &compiled_program.program, @@ -133,16 +122,17 @@ pub fn run_test>( |program: &Program, initial_witness: WitnessMap| -> Result, String> { + // Use a base layer that doesn't handle anything, which we handle in the `execute` below. + let inner_executor = + build_foreign_call_executor(PrintOutput::None, layers::Unhandled); + let mut foreign_call_executor = + TestForeignCallExecutor::new(inner_executor); + let circuit_execution = execute_program( program, initial_witness, blackbox_solver, - &mut TestForeignCallExecutor::::new( - PrintOutput::None, - foreign_call_resolver_url, - root_path.clone(), - package_name.clone(), - ), + &mut foreign_call_executor, ); let status = test_status_program_compile_pass( @@ -278,38 +268,21 @@ fn check_expected_failure_message( } /// A specialized foreign call executor which tracks whether it has encountered any unknown foreign calls -struct TestForeignCallExecutor<'a, F> { - /// The executor for any [`ForeignCall::Print`] calls. - printer: PrintForeignCallExecutor<'a>, - mocker: MockForeignCallExecutor, - external: Option, - +struct TestForeignCallExecutor { + executor: E, encountered_unknown_foreign_call: bool, } -impl<'a, F: Default> TestForeignCallExecutor<'a, F> { - fn new( - output: PrintOutput<'a>, - resolver_url: Option<&str>, - root_path: Option, - package_name: Option, - ) -> Self { - let id = rand::thread_rng().gen(); - let printer = PrintForeignCallExecutor { output }; - let external_resolver = resolver_url.map(|resolver_url| { - RPCForeignCallExecutor::new(resolver_url, id, root_path, package_name) - }); - TestForeignCallExecutor { - printer, - mocker: MockForeignCallExecutor::default(), - external: external_resolver, - encountered_unknown_foreign_call: false, - } +impl TestForeignCallExecutor { + fn new(executor: E) -> Self { + Self { executor, encountered_unknown_foreign_call: false } } } -impl<'a, F: AcirField + Serialize + for<'b> Deserialize<'b>> ForeignCallExecutor - for TestForeignCallExecutor<'a, F> +impl ForeignCallExecutor for TestForeignCallExecutor +where + F: AcirField, + E: ForeignCallExecutor, { fn execute( &mut self, @@ -317,46 +290,14 @@ impl<'a, F: AcirField + Serialize + for<'b> Deserialize<'b>> ForeignCallExecutor ) -> Result, ForeignCallError> { // If the circuit has reached a new foreign call opcode then it can't have failed from any previous unknown foreign calls. self.encountered_unknown_foreign_call = false; - - let foreign_call_name = foreign_call.function.as_str(); - match ForeignCall::lookup(foreign_call_name) { - Some(ForeignCall::Print) => self.printer.execute(foreign_call), - - Some( - ForeignCall::CreateMock - | ForeignCall::SetMockParams - | ForeignCall::GetMockLastParams - | ForeignCall::SetMockReturns - | ForeignCall::SetMockTimes - | ForeignCall::ClearMock, - ) => self.mocker.execute(foreign_call), - - None => { - // First check if there's any defined mock responses for this foreign call. - match self.mocker.execute(foreign_call) { - Err(ForeignCallError::NoHandler(_)) => (), - response_or_error => return response_or_error, - }; - - if let Some(external_resolver) = &mut self.external { - // If the user has registered an external resolver then we forward any remaining oracle calls there. - match external_resolver.execute(foreign_call) { - Err(ForeignCallError::NoHandler(_)) => (), - response_or_error => return response_or_error, - }; - } - + match self.executor.execute(foreign_call) { + Err(ForeignCallError::NoHandler(_)) => { self.encountered_unknown_foreign_call = true; - - // If all executors have no handler for the given foreign call then we cannot - // return a correct response to the ACVM. The best we can do is to return an empty response, - // this allows us to ignore any foreign calls which exist solely to pass information from inside - // the circuit to the environment (e.g. custom logging) as the execution will still be able to progress. - // - // We optimistically return an empty response for all oracle calls as the ACVM will error - // should a response have been required. - Ok(ForeignCallResult::default()) + // If the inner executor cannot handle this foreign call, then it's very likely that this is a custom + // foreign call. We then return an empty response in case the foreign call doesn't need return values. + layers::Empty.execute(foreign_call) } + other => other, } } } diff --git a/noir/noir-repo/tooling/nargo_cli/Cargo.toml b/noir/noir-repo/tooling/nargo_cli/Cargo.toml index 5603b7f4fca..f7a98b4c278 100644 --- a/noir/noir-repo/tooling/nargo_cli/Cargo.toml +++ b/noir/noir-repo/tooling/nargo_cli/Cargo.toml @@ -27,7 +27,13 @@ clap.workspace = true fm.workspace = true fxhash.workspace = true iter-extended.workspace = true -nargo.workspace = true +# This is the only crate that really needs the RPC feature, +# but enabling it here implicitly enables it for the whole +# workspace. A crate could opt out using `path` dependency, +# but it's only `noir_wasm` which couldn't compile with it, +# and that is a different target, and for that the feature +# aren't unified with this one. +nargo = { workspace = true, features = ["rpc"] } nargo_fmt.workspace = true nargo_toml.workspace = true noir_lsp.workspace = true @@ -88,12 +94,10 @@ proptest.workspace = true sha2.workspace = true sha3.workspace = true iai = "0.1.1" -test-binary = "3.0.2" test-case.workspace = true lazy_static.workspace = true light-poseidon = "0.2.0" - [[bench]] name = "criterion" harness = false diff --git a/noir/noir-repo/tooling/nargo_cli/benches/criterion.rs b/noir/noir-repo/tooling/nargo_cli/benches/criterion.rs index 9bc50f87d8e..3d81ade65bc 100644 --- a/noir/noir-repo/tooling/nargo_cli/benches/criterion.rs +++ b/noir/noir-repo/tooling/nargo_cli/benches/criterion.rs @@ -3,7 +3,6 @@ use acvm::{acir::native_types::WitnessMap, FieldElement}; use assert_cmd::prelude::{CommandCargoExt, OutputAssertExt}; use criterion::{criterion_group, criterion_main, Criterion}; -use nargo::PrintOutput; use noirc_abi::{ input_parser::{Format, InputValue}, Abi, InputMap, @@ -116,7 +115,7 @@ fn criterion_test_execution(c: &mut Criterion, test_program_dir: &Path, force_br let artifacts = RefCell::new(None); let mut foreign_call_executor = - nargo::foreign_calls::DefaultForeignCallExecutor::new(PrintOutput::None, None, None, None); + nargo::foreign_calls::DefaultForeignCallBuilder::default().build(); c.bench_function(&benchmark_name, |b| { b.iter_batched( diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs index ee8ff32922e..6320cbbf350 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/info_cmd.rs @@ -3,8 +3,7 @@ use bn254_blackbox_solver::Bn254BlackBoxSolver; use clap::Args; use iter_extended::vecmap; use nargo::{ - constants::PROVER_INPUT_FILE, foreign_calls::DefaultForeignCallExecutor, package::Package, - PrintOutput, + constants::PROVER_INPUT_FILE, foreign_calls::DefaultForeignCallBuilder, package::Package, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; use noirc_abi::input_parser::Format; @@ -255,7 +254,7 @@ fn profile_brillig_execution( &program_artifact.bytecode, initial_witness, &Bn254BlackBoxSolver, - &mut DefaultForeignCallExecutor::new(PrintOutput::None, None, None, None), + &mut DefaultForeignCallBuilder::default().build(), )?; let expression_width = get_target_width(package.expression_width, expression_width); diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs index f9736d0b79e..0aa31f36686 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/test_cmd.rs @@ -14,8 +14,9 @@ use clap::Args; use fm::FileManager; use formatters::{Formatter, JsonFormatter, PrettyFormatter, TerseFormatter}; use nargo::{ - insert_all_files_for_workspace_into_file_manager, ops::TestStatus, package::Package, parse_all, - prepare_package, workspace::Workspace, PrintOutput, + foreign_calls::DefaultForeignCallBuilder, insert_all_files_for_workspace_into_file_manager, + ops::TestStatus, package::Package, parse_all, prepare_package, workspace::Workspace, + PrintOutput, }; use nargo_toml::{get_package_manifest, resolve_workspace_from_toml}; use noirc_driver::{check_crate, CompileOptions, NOIR_ARTIFACT_VERSION_STRING}; @@ -507,10 +508,16 @@ impl<'a> TestRunner<'a> { &mut context, test_function, PrintOutput::String(&mut output_string), - foreign_call_resolver_url, - root_path, - Some(package_name), &self.args.compile_options, + |output, base| { + DefaultForeignCallBuilder { + output, + resolver_url: foreign_call_resolver_url.map(|s| s.to_string()), + root_path: root_path.clone(), + package_name: Some(package_name.clone()), + } + .build_with_base(base) + }, ); (test_status, output_string) } diff --git a/noir/noir-repo/tooling/nargo_cli/tests/execute.rs b/noir/noir-repo/tooling/nargo_cli/tests/execute.rs index 561520c57a9..77d77cfd902 100644 --- a/noir/noir-repo/tooling/nargo_cli/tests/execute.rs +++ b/noir/noir-repo/tooling/nargo_cli/tests/execute.rs @@ -12,8 +12,6 @@ mod tests { use super::*; - test_binary::build_test_binary_once!(mock_backend, "../backend_interface/test-binaries"); - // Utilities to keep the test matrix labels more intuitive. #[derive(Debug, Clone, Copy)] struct ForceBrillig(pub bool); diff --git a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-props.rs b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-props.rs index 9750eb823a6..8f08703ab04 100644 --- a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-props.rs +++ b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-props.rs @@ -2,9 +2,7 @@ use std::{cell::RefCell, collections::BTreeMap, path::Path}; use acvm::{acir::native_types::WitnessStack, AcirField, FieldElement}; use iter_extended::vecmap; -use nargo::{ - foreign_calls::DefaultForeignCallExecutor, ops::execute_program, parse_all, PrintOutput, -}; +use nargo::{foreign_calls::DefaultForeignCallBuilder, ops::execute_program, parse_all}; use noirc_abi::input_parser::InputValue; use noirc_driver::{ compile_main, file_manager_with_stdlib, prepare_crate, CompilationResult, CompileOptions, @@ -81,8 +79,7 @@ fn run_snippet_proptest( }; let blackbox_solver = bn254_blackbox_solver::Bn254BlackBoxSolver; - let foreign_call_executor = - RefCell::new(DefaultForeignCallExecutor::new(PrintOutput::None, None, None, None)); + let foreign_call_executor = RefCell::new(DefaultForeignCallBuilder::default().build()); // Generate multiple input/output proptest!(ProptestConfig::with_cases(100), |(io in strategy)| { diff --git a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs index 29b871814b8..6aae94f6645 100644 --- a/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs +++ b/noir/noir-repo/tooling/nargo_cli/tests/stdlib-tests.rs @@ -2,6 +2,7 @@ #![allow(clippy::items_after_test_module)] use clap::Parser; use fm::FileManager; +use nargo::foreign_calls::DefaultForeignCallBuilder; use nargo::PrintOutput; use noirc_driver::{check_crate, file_manager_with_stdlib, CompileOptions}; use noirc_frontend::hir::FunctionNameMatch; @@ -88,10 +89,10 @@ fn run_stdlib_tests(force_brillig: bool, inliner_aggressiveness: i64) { &mut context, &test_function, PrintOutput::Stdout, - None, - Some(dummy_package.root_dir.clone()), - Some(dummy_package.name.to_string()), &CompileOptions { force_brillig, inliner_aggressiveness, ..Default::default() }, + |output, base| { + DefaultForeignCallBuilder { output, ..Default::default() }.build_with_base(base) + }, ); (test_name, status) }) diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/function.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/function.rs index 8207db5e486..ca905f3dcf8 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/function.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/function.rs @@ -19,10 +19,11 @@ pub(super) struct FunctionToFormat { pub(super) return_visibility: Visibility, pub(super) where_clause: Vec, pub(super) body: Option, + pub(super) skip_visibility: bool, } impl<'a> Formatter<'a> { - pub(super) fn format_function(&mut self, func: NoirFunction) { + pub(super) fn format_function(&mut self, func: NoirFunction, skip_visibility: bool) { self.format_function_impl(FunctionToFormat { attributes: func.def.attributes, visibility: func.def.visibility, @@ -33,6 +34,7 @@ impl<'a> Formatter<'a> { return_visibility: func.def.return_visibility, where_clause: func.def.where_clause, body: Some(func.def.body), + skip_visibility, }); } @@ -41,7 +43,7 @@ impl<'a> Formatter<'a> { self.format_attributes(func.attributes); self.write_indentation(); - self.format_function_modifiers(func.visibility); + self.format_function_modifiers(func.visibility, func.skip_visibility); self.write_keyword(Keyword::Fn); self.write_space(); self.write_identifier(func.name); @@ -94,7 +96,11 @@ impl<'a> Formatter<'a> { } } - pub(super) fn format_function_modifiers(&mut self, visibility: ItemVisibility) { + pub(super) fn format_function_modifiers( + &mut self, + visibility: ItemVisibility, + skip_visibility: bool, + ) { // For backwards compatibility, unconstrained might come before visibility. // We'll remember this but put it after the visibility. let unconstrained = if self.is_at_keyword(Keyword::Unconstrained) { @@ -105,7 +111,14 @@ impl<'a> Formatter<'a> { false }; - self.format_item_visibility(visibility); + if skip_visibility { + // The intention here is to format the visibility into a temporary buffer that is discarded + self.chunk_formatter().chunk(|formatter| { + formatter.format_item_visibility(visibility); + }); + } else { + self.format_item_visibility(visibility); + } if unconstrained { self.write("unconstrained "); diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/impls.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/impls.rs index 1c2c25c9200..71548dd5efa 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/impls.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/impls.rs @@ -38,7 +38,9 @@ impl<'a> Formatter<'a> { if !doc_comments.is_empty() { self.format_outer_doc_comments(); } - self.format_function(method); + self.format_function( + method, false, // skip visibility + ); } self.skip_comments_and_whitespace(); diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/item.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/item.rs index 521e476fe71..3365e52ec29 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/item.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/item.rs @@ -58,7 +58,10 @@ impl<'a> Formatter<'a> { ItemKind::Import(use_tree, item_visibility) => { self.format_import(use_tree, item_visibility); } - ItemKind::Function(noir_function) => self.format_function(noir_function), + ItemKind::Function(noir_function) => self.format_function( + noir_function, + false, // skip visibility + ), ItemKind::Struct(noir_struct) => self.format_struct(noir_struct), ItemKind::Trait(noir_trait) => self.format_trait(noir_trait), ItemKind::TraitImpl(noir_trait_impl) => self.format_trait_impl(noir_trait_impl), diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/trait_impl.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/trait_impl.rs index b31da8a4101..5bb9a0d0025 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/trait_impl.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/trait_impl.rs @@ -1,8 +1,5 @@ use noirc_frontend::{ - ast::{ - FunctionDefinition, ItemVisibility, NoirFunction, NoirTraitImpl, Pattern, TraitImplItem, - TraitImplItemKind, - }, + ast::{NoirTraitImpl, Pattern, TraitImplItem, TraitImplItemKind}, token::{Keyword, Token}, }; @@ -69,12 +66,10 @@ impl<'a> Formatter<'a> { fn format_trait_impl_item(&mut self, item: TraitImplItem) { match item.kind { TraitImplItemKind::Function(noir_function) => { - // Trait impl functions are public, but there's no `pub` keyword in the source code, - // so to format it we pass a private one. - let def = - FunctionDefinition { visibility: ItemVisibility::Private, ..noir_function.def }; - let noir_function = NoirFunction { def, ..noir_function }; - self.format_function(noir_function); + self.format_function( + noir_function, + true, // skip visibility + ); } TraitImplItemKind::Constant(name, typ, value) => { let pattern = Pattern::Identifier(name); @@ -179,6 +174,22 @@ fn foo ( ) { } assert_format(src, expected); } + #[test] + fn format_trait_impl_function_with_visibility() { + let src = " mod moo { impl Foo for Bar { + /// Some doc comment +pub fn foo ( ) { } + } }"; + let expected = "mod moo { + impl Foo for Bar { + /// Some doc comment + fn foo() {} + } +} +"; + assert_format(src, expected); + } + #[test] fn format_trait_impl_constant_without_type() { let src = " mod moo { impl Foo for Bar { diff --git a/noir/noir-repo/tooling/nargo_fmt/src/formatter/traits.rs b/noir/noir-repo/tooling/nargo_fmt/src/formatter/traits.rs index 1f192be471e..175dcad6170 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/formatter/traits.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/formatter/traits.rs @@ -113,6 +113,7 @@ impl<'a> Formatter<'a> { return_visibility: Visibility::Private, where_clause, body, + skip_visibility: true, }; self.format_function_impl(func); } @@ -236,12 +237,12 @@ mod tests { fn format_trait_with_function_without_body() { let src = " mod moo { trait Foo { /// hello - pub fn foo ( ); + fn foo ( ); } }"; let expected = "mod moo { trait Foo { /// hello - pub fn foo(); + fn foo(); } } "; @@ -252,12 +253,12 @@ mod tests { fn format_trait_with_function_with_body() { let src = " mod moo { trait Foo { /// hello - pub fn foo ( ) { 1 } + fn foo ( ) { 1 } } }"; let expected = "mod moo { trait Foo { /// hello - pub fn foo() { + fn foo() { 1 } } @@ -270,12 +271,12 @@ mod tests { fn format_trait_with_function_with_params() { let src = " mod moo { trait Foo { /// hello - pub fn foo ( x : i32 , y : Field ); + fn foo ( x : i32 , y : Field ); } }"; let expected = "mod moo { trait Foo { /// hello - pub fn foo(x: i32, y: Field); + fn foo(x: i32, y: Field); } } "; @@ -298,6 +299,24 @@ mod tests { assert_format(src, expected); } + #[test] + fn format_trait_with_function_with_visibility() { + let src = " mod moo { trait Foo { + /// hello + pub fn foo ( ) { 1 } + } }"; + let expected = "mod moo { + trait Foo { + /// hello + fn foo() { + 1 + } + } +} +"; + assert_format(src, expected); + } + #[test] fn format_multiple_traits() { let src = " trait Foo {} diff --git a/noir/noir-repo/tooling/nargo_fmt/src/lib.rs b/noir/noir-repo/tooling/nargo_fmt/src/lib.rs index eda77e78c7c..2b55b86e975 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/lib.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/lib.rs @@ -66,6 +66,7 @@ pub(crate) fn assert_format_with_config(src: &str, expected: &str, config: Confi use noirc_frontend::parser; let (parsed_module, errors) = parser::parse_program(src); + let errors: Vec<_> = errors.into_iter().filter(|error| !error.is_warning()).collect(); if !errors.is_empty() { panic!("Expected no errors, got: {:?}", errors); } diff --git a/noir/noir-repo/tooling/noirc_abi/src/lib.rs b/noir/noir-repo/tooling/noirc_abi/src/lib.rs index bd5674d64f1..5f5f3748bc4 100644 --- a/noir/noir-repo/tooling/noirc_abi/src/lib.rs +++ b/noir/noir-repo/tooling/noirc_abi/src/lib.rs @@ -13,10 +13,7 @@ use acvm::{ use errors::AbiError; use input_parser::InputValue; use iter_extended::{try_btree_map, try_vecmap, vecmap}; -use noirc_printable_type::{ - decode_value as printable_type_decode_value, PrintableType, PrintableValue, - PrintableValueDisplay, -}; +use noirc_printable_type::{PrintableType, PrintableValue, PrintableValueDisplay}; use serde::{Deserialize, Serialize}; use std::borrow::Borrow; use std::{collections::BTreeMap, str}; @@ -30,8 +27,11 @@ mod arbitrary; pub mod errors; pub mod input_parser; +mod printable_type; mod serialization; +pub use printable_type::decode_value as decode_printable_value; + /// A map from the fields in an TOML/JSON file which correspond to some ABI to their values pub type InputMap = BTreeMap; @@ -417,7 +417,7 @@ pub fn decode_value( Ok(value) } -fn decode_string_value(field_elements: &[FieldElement]) -> String { +pub fn decode_string_value(field_elements: &[F]) -> String { let string_as_slice = vecmap(field_elements, |e| { let mut field_as_bytes = e.to_be_bytes(); let char_byte = field_as_bytes.pop().unwrap(); // A character in a string is represented by a u8, thus we just want the last byte of the element @@ -476,21 +476,21 @@ pub fn display_abi_error( AbiErrorType::FmtString { length, item_types } => { let mut fields_iter = fields.iter().copied(); let PrintableValue::String(string) = - printable_type_decode_value(&mut fields_iter, &PrintableType::String { length }) + decode_printable_value(&mut fields_iter, &PrintableType::String { length }) else { unreachable!("Got non-string from string decoding"); }; let _length_of_items = fields_iter.next(); let items = item_types.into_iter().map(|abi_type| { let printable_typ = (&abi_type).into(); - let decoded = printable_type_decode_value(&mut fields_iter, &printable_typ); + let decoded = decode_printable_value(&mut fields_iter, &printable_typ); (decoded, printable_typ) }); PrintableValueDisplay::FmtString(string, items.collect()) } AbiErrorType::Custom(abi_typ) => { let printable_type = (&abi_typ).into(); - let decoded = printable_type_decode_value(&mut fields.iter().copied(), &printable_type); + let decoded = decode_printable_value(&mut fields.iter().copied(), &printable_type); PrintableValueDisplay::Plain(decoded, printable_type) } AbiErrorType::String { string } => { diff --git a/noir/noir-repo/tooling/noirc_abi/src/printable_type.rs b/noir/noir-repo/tooling/noirc_abi/src/printable_type.rs new file mode 100644 index 00000000000..a81eb0ce8f6 --- /dev/null +++ b/noir/noir-repo/tooling/noirc_abi/src/printable_type.rs @@ -0,0 +1,78 @@ +use std::collections::BTreeMap; + +use acvm::acir::AcirField; +use iter_extended::vecmap; + +use noirc_printable_type::{PrintableType, PrintableValue}; + +use crate::decode_string_value; + +/// Assumes that `field_iterator` contains enough field elements in order to decode the [PrintableType] +pub fn decode_value( + field_iterator: &mut impl Iterator, + typ: &PrintableType, +) -> PrintableValue { + match typ { + PrintableType::Field + | PrintableType::SignedInteger { .. } + | PrintableType::UnsignedInteger { .. } + | PrintableType::Boolean => { + let field_element = field_iterator.next().unwrap(); + + PrintableValue::Field(field_element) + } + PrintableType::Array { length, typ } => { + let length = *length as usize; + let mut array_elements = Vec::with_capacity(length); + for _ in 0..length { + array_elements.push(decode_value(field_iterator, typ)); + } + + PrintableValue::Vec { array_elements, is_slice: false } + } + PrintableType::Slice { typ } => { + let length = field_iterator + .next() + .expect("not enough data to decode variable array length") + .to_u128() as usize; + let mut array_elements = Vec::with_capacity(length); + for _ in 0..length { + array_elements.push(decode_value(field_iterator, typ)); + } + + PrintableValue::Vec { array_elements, is_slice: true } + } + PrintableType::Tuple { types } => PrintableValue::Vec { + array_elements: vecmap(types, |typ| decode_value(field_iterator, typ)), + is_slice: false, + }, + PrintableType::String { length } => { + let field_elements: Vec = field_iterator.take(*length as usize).collect(); + + PrintableValue::String(decode_string_value(&field_elements)) + } + PrintableType::Struct { fields, .. } => { + let mut struct_map = BTreeMap::new(); + + for (field_key, param_type) in fields { + let field_value = decode_value(field_iterator, param_type); + + struct_map.insert(field_key.to_owned(), field_value); + } + + PrintableValue::Struct(struct_map) + } + PrintableType::Function { env, .. } => { + let field_element = field_iterator.next().unwrap(); + let func_ref = PrintableValue::Field(field_element); + // we want to consume the fields from the environment, but for now they are not actually printed + decode_value(field_iterator, env); + func_ref + } + PrintableType::MutableReference { typ } => { + // we decode the reference, but it's not really used for printing + decode_value(field_iterator, typ) + } + PrintableType::Unit => PrintableValue::Field(F::zero()), + } +} diff --git a/noir/noir-repo/tooling/noirc_artifacts/src/debug_vars.rs b/noir/noir-repo/tooling/noirc_artifacts/src/debug_vars.rs index aa9328432b8..8efeeebb3aa 100644 --- a/noir/noir-repo/tooling/noirc_artifacts/src/debug_vars.rs +++ b/noir/noir-repo/tooling/noirc_artifacts/src/debug_vars.rs @@ -1,8 +1,9 @@ use acvm::AcirField; +use noirc_abi::decode_printable_value; use noirc_errors::debug_info::{ DebugFnId, DebugFunction, DebugInfo, DebugTypeId, DebugVarId, DebugVariable, }; -use noirc_printable_type::{decode_value, PrintableType, PrintableValue}; +use noirc_printable_type::{PrintableType, PrintableValue}; use std::collections::HashMap; #[derive(Debug, Default, Clone)] @@ -45,7 +46,7 @@ impl DebugVars { &'a self, fn_id: &DebugFnId, frame: &'a HashMap>, - ) -> StackFrame { + ) -> StackFrame<'a, F> { let debug_fn = &self.functions.get(fn_id).expect("failed to find function metadata"); let params: Vec<&str> = @@ -72,7 +73,7 @@ impl DebugVars { .last_mut() .expect("unexpected empty stack frames") .1 - .insert(var_id, decode_value(&mut values.iter().copied(), ptype)); + .insert(var_id, decode_printable_value(&mut values.iter().copied(), ptype)); } pub fn assign_field(&mut self, var_id: DebugVarId, indexes: Vec, values: &[F]) { @@ -143,7 +144,7 @@ impl DebugVars { } }; } - *cursor = decode_value(&mut values.iter().copied(), cursor_type); + *cursor = decode_printable_value(&mut values.iter().copied(), cursor_type); } pub fn assign_deref(&mut self, _var_id: DebugVarId, _values: &[F]) { diff --git a/noir/noir-repo/tooling/profiler/src/cli/execution_flamegraph_cmd.rs b/noir/noir-repo/tooling/profiler/src/cli/execution_flamegraph_cmd.rs index 76b23ebf739..bab15529744 100644 --- a/noir/noir-repo/tooling/profiler/src/cli/execution_flamegraph_cmd.rs +++ b/noir/noir-repo/tooling/profiler/src/cli/execution_flamegraph_cmd.rs @@ -3,13 +3,13 @@ use std::path::{Path, PathBuf}; use acir::circuit::OpcodeLocation; use clap::Args; use color_eyre::eyre::{self, Context}; +use nargo::foreign_calls::DefaultForeignCallBuilder; use nargo::PrintOutput; use crate::flamegraph::{BrilligExecutionSample, FlamegraphGenerator, InfernoFlamegraphGenerator}; use crate::fs::{read_inputs_from_file, read_program_from_file}; use crate::opcode_formatter::format_brillig_opcode; use bn254_blackbox_solver::Bn254BlackBoxSolver; -use nargo::foreign_calls::DefaultForeignCallExecutor; use noirc_abi::input_parser::Format; use noirc_artifacts::debug::DebugArtifact; @@ -55,7 +55,7 @@ fn run_with_generator( &program.bytecode, initial_witness, &Bn254BlackBoxSolver, - &mut DefaultForeignCallExecutor::new(PrintOutput::Stdout, None, None, None), + &mut DefaultForeignCallBuilder::default().with_output(PrintOutput::Stdout).build(), )?; println!("Executed");