diff --git a/.circleci/config.yml b/.circleci/config.yml index fd4aec7d778..6b4c8af64ae 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -551,15 +551,15 @@ jobs: aztec_manifest_key: end-to-end <<: *defaults_e2e_test - # bench-tx-size: - # steps: - # - *checkout - # - *setup_env - # - run: - # name: "Benchmark" - # command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose-no-sandbox.yml TEST=benchmarks/bench_tx_size_fees.test.ts ENABLE_GAS=1 DEBUG=aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees - # aztec_manifest_key: end-to-end - # <<: *defaults_e2e_test + bench-tx-size: + steps: + - *checkout + - *setup_env + - run: + name: "Benchmark" + command: cond_spot_run_compose end-to-end 4 ./scripts/docker-compose-no-sandbox.yml TEST=benchmarks/bench_tx_size_fees.test.ts ENABLE_GAS=1 DEBUG=aztec:benchmarks:*,aztec:sequencer,aztec:sequencer:*,aztec:world_state,aztec:merkle_trees + aztec_manifest_key: end-to-end + <<: *defaults_e2e_test build-docs: machine: @@ -900,12 +900,12 @@ workflows: # Benchmark jobs. - bench-publish-rollup: *e2e_test - bench-process-history: *e2e_test - # - bench-tx-size: *e2e_test + - bench-tx-size: *e2e_test - bench-summary: requires: - bench-publish-rollup - bench-process-history - # - bench-tx-size + - bench-tx-size <<: *defaults # Production releases. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 72b97bb2e1d..8ad90c70469 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,8 +44,9 @@ jobs: # prepare images locally, tagged by commit hash - name: "Build E2E Image" timeout-minutes: 40 - run: earthly ./yarn-project+export-end-to-end + run: earthly-ci ./yarn-project+export-end-to-end # We base our e2e list used in e2e-x86 off the targets in ./yarn-project/end-to-end + # (Note ARM uses just 2 tests as a smoketest) - name: Create list of end-to-end jobs id: e2e_list run: echo "list=$(earthly ls ./yarn-project/end-to-end | grep -v '+base' | sed 's/+//' | jq -R . | jq -cs .)" >> $GITHUB_OUTPUT @@ -68,7 +69,7 @@ jobs: - name: Test working-directory: ./yarn-project/end-to-end/ timeout-minutes: 25 - run: earthly -P --no-output +${{ matrix.test }} --e2e_mode=cache + run: earthly-ci -P --no-output +${{ matrix.test }} --e2e_mode=cache # TODO # - name: Upload logs # run: BRANCH=${{ github.ref_name }} PULL_REQUEST=${{ github.event.number }} scripts/ci/upload_logs_to_s3 ./yarn-project/end-to-end/log @@ -92,7 +93,7 @@ jobs: working-directory: ./barretenberg/cpp/ timeout-minutes: 25 # limit our parallelism to half our cores - run: earthly --no-output +test --hardware_concurrency=64 + run: earthly-ci --no-output +test --hardware_concurrency=64 # push benchmarking binaries to dockerhub registry bb-bench-binaries: @@ -108,7 +109,7 @@ jobs: if: ${{ github.event.inputs.just_start_spot != 'true' }} timeout-minutes: 15 working-directory: ./barretenberg/cpp/ - run: earthly --push +bench-binaries + run: earthly-ci --push +bench-binaries setup-bench: uses: ./.github/workflows/setup-runner.yml @@ -136,15 +137,30 @@ jobs: - name: Client IVC Bench working-directory: ./barretenberg/cpp/ timeout-minutes: 15 - run: earthly --no-output +bench-client-ivc --bench_mode=cache + run: earthly-ci --no-output +bench-client-ivc --bench_mode=cache - name: Ultrahonk Bench working-directory: ./barretenberg/cpp/ timeout-minutes: 15 - run: earthly --no-output +bench-ultra-honk --bench_mode=cache + run: earthly-ci --no-output +bench-ultra-honk --bench_mode=cache merge-check: runs-on: ${{ github.actor }}-x86 needs: [e2e, bb-native-tests, bb-bench] steps: - run: echo Pull request merging now allowed. + + notify: + needs: [e2e, bb-native-tests, bb-bench] + runs-on: ubuntu-latest + if: ${{ github.ref == 'refs/heads/master' && failure() }} + steps: + - name: Send notification to aztec3-ci channel if workflow failed on master + uses: slackapi/slack-github-action@v1.25.0 + with: + payload: | + { + "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_NOTIFY_WORKFLOW_TRIGGER_URL }} diff --git a/.github/workflows/setup-runner.yml b/.github/workflows/setup-runner.yml index 15b670c82ec..c581738eace 100644 --- a/.github/workflows/setup-runner.yml +++ b/.github/workflows/setup-runner.yml @@ -3,7 +3,7 @@ # just for the CI job. These are specced per user and run the entire CI. # TODO These have a persistent EBS volume that forms a fast-online docker image cache (used by Earthly), meaning # TODO build steps that ran in previous invocations are quickly ran from cache. -name: Reusable Spot Instance and Setup Workflow +name: Setup Runner and CI on: workflow_call: inputs: @@ -52,9 +52,12 @@ on: jobs: start-builder: runs-on: ubuntu-latest + # we want to avoid race conditions when making spot across multiple PRs as we only use one runner + concurrency: + group: start-builder-${{ inputs.runner_label }} steps: - name: Start EC2 runner - uses: AztecProtocol/ec2-action-builder@v0.10 + uses: AztecProtocol/ec2-action-builder@v0.13 with: github_token: ${{ secrets.GH_SELF_HOSTED_RUNNER_TOKEN }} aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} diff --git a/.github/workflows/start-spot.yml b/.github/workflows/start-spot.yml index 2cbc0e8415d..350d6520cd8 100644 --- a/.github/workflows/start-spot.yml +++ b/.github/workflows/start-spot.yml @@ -1,5 +1,5 @@ # Useful if the spot runners are in a bad state -name: Stop Personal Spot +name: Start Personal Spot on: workflow_dispatch: {} jobs: @@ -27,4 +27,4 @@ jobs: ec2_instance_type: m6a.4xlarge ec2_ami_id: ami-0d8a9b0419ddb331a ec2_instance_ttl: 15 - secrets: inherit \ No newline at end of file + secrets: inherit diff --git a/.noir-sync-commit b/.noir-sync-commit index 64da23777cd..8f6aafb96d3 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -1d96937a8e94a91c0c17c97102498d067fca76c3 +6cc105ee441e093b4fccdd5fcc3db922eb28a3fb diff --git a/avm-transpiler/Cargo.lock b/avm-transpiler/Cargo.lock index b99f5b35be6..6fc2aa934f5 100644 --- a/avm-transpiler/Cargo.lock +++ b/avm-transpiler/Cargo.lock @@ -51,6 +51,7 @@ dependencies = [ "blake3", "k256", "keccak", + "num-bigint", "p256", "sha2", "sha3", @@ -185,7 +186,7 @@ dependencies = [ "ark-std", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -202,7 +203,7 @@ dependencies = [ "ark-std", "derivative", "digest", - "itertools", + "itertools 0.10.5", "num-bigint", "num-traits", "paste", @@ -291,6 +292,15 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -355,6 +365,33 @@ dependencies = [ "serde", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + [[package]] name = "bitmaps" version = "2.1.0" @@ -464,7 +501,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets", + "windows-targets 0.52.0", ] [[package]] @@ -587,6 +624,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.4.9" @@ -686,6 +729,27 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "ecdsa" version = "0.14.8" @@ -724,6 +788,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ena" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +dependencies = [ + "log", +] + [[package]] name = "env_filter" version = "0.1.0" @@ -970,6 +1043,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -1018,12 +1100,63 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools 0.11.0", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata", +] + [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.20" @@ -1056,6 +1189,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "noirc_abi" version = "0.27.0" @@ -1136,6 +1275,8 @@ dependencies = [ "chumsky", "fm", "iter-extended", + "lalrpop", + "lalrpop-util", "noirc_errors", "noirc_printable_type", "petgraph", @@ -1209,6 +1350,29 @@ dependencies = [ "sha2", ] +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + [[package]] name = "paste" version = "1.0.14" @@ -1225,6 +1389,21 @@ dependencies = [ "indexmap 2.2.1", ] +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -1253,6 +1432,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "proc-macro2" version = "1.0.78" @@ -1309,6 +1494,26 @@ dependencies = [ "rand_core", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.3" @@ -1398,6 +1603,12 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" + [[package]] name = "ryu" version = "1.0.16" @@ -1466,6 +1677,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sec1" version = "0.3.0" @@ -1595,6 +1812,12 @@ dependencies = [ "rand_core", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "sized-chunks" version = "0.6.5" @@ -1639,6 +1862,19 @@ dependencies = [ "der", ] +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.10.0" @@ -1673,6 +1909,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -1731,6 +1978,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "toml" version = "0.7.8" @@ -1820,6 +2076,12 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "utf8parse" version = "0.2.1" @@ -1939,7 +2201,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", ] [[package]] @@ -1948,7 +2210,22 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1957,51 +2234,93 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.0" diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index 0de09a5793c..fda785f1ff9 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -1,5 +1,4 @@ use acvm::acir::brillig::Opcode as BrilligOpcode; -use acvm::acir::circuit::brillig::Brillig; use acvm::brillig_vm::brillig::{ BinaryFieldOp, BinaryIntOp, BlackBoxOp, HeapArray, HeapVector, MemoryAddress, ValueOrArray, @@ -14,17 +13,17 @@ use crate::opcodes::AvmOpcode; use crate::utils::{dbg_print_avm_program, dbg_print_brillig_program}; /// Transpile a Brillig program to AVM bytecode -pub fn brillig_to_avm(brillig: &Brillig) -> Vec { - dbg_print_brillig_program(brillig); +pub fn brillig_to_avm(brillig_bytecode: &[BrilligOpcode]) -> Vec { + dbg_print_brillig_program(brillig_bytecode); let mut avm_instrs: Vec = Vec::new(); // Map Brillig pcs to AVM pcs // (some Brillig instructions map to >1 AVM instruction) - let brillig_pcs_to_avm_pcs = map_brillig_pcs_to_avm_pcs(avm_instrs.len(), brillig); + let brillig_pcs_to_avm_pcs = map_brillig_pcs_to_avm_pcs(avm_instrs.len(), brillig_bytecode); // Transpile a Brillig instruction to one or more AVM instructions - for brillig_instr in &brillig.bytecode { + for brillig_instr in brillig_bytecode { match brillig_instr { BrilligOpcode::BinaryFieldOp { destination, @@ -1090,12 +1089,15 @@ fn handle_storage_read( /// brillig: the Brillig program /// returns: an array where each index is a Brillig pc, /// and each value is the corresponding AVM pc. -fn map_brillig_pcs_to_avm_pcs(initial_offset: usize, brillig: &Brillig) -> Vec { - let mut pc_map = vec![0; brillig.bytecode.len()]; +fn map_brillig_pcs_to_avm_pcs( + initial_offset: usize, + brillig_bytecode: &[BrilligOpcode], +) -> Vec { + let mut pc_map = vec![0; brillig_bytecode.len()]; pc_map[0] = initial_offset; - for i in 0..brillig.bytecode.len() - 1 { - let num_avm_instrs_for_this_brillig_instr = match &brillig.bytecode[i] { + for i in 0..brillig_bytecode.len() - 1 { + let num_avm_instrs_for_this_brillig_instr = match &brillig_bytecode[i] { BrilligOpcode::Const { bit_size: 254, .. } => 2, _ => 1, }; diff --git a/avm-transpiler/src/transpile_contract.rs b/avm-transpiler/src/transpile_contract.rs index 537dfb34bb3..e28b20aa4a3 100644 --- a/avm-transpiler/src/transpile_contract.rs +++ b/avm-transpiler/src/transpile_contract.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use acvm::acir::circuit::Program; use crate::transpile::brillig_to_avm; -use crate::utils::extract_brillig_from_acir; +use crate::utils::extract_brillig_from_acir_program; /// Representation of a contract with some transpiled functions #[derive(Debug, Serialize, Deserialize)] @@ -88,10 +88,10 @@ impl From for TranspiledContract { ); // Extract Brillig Opcodes from acir let acir_program = function.bytecode; - let brillig = extract_brillig_from_acir(&acir_program.functions[0].opcodes); + let brillig_bytecode = extract_brillig_from_acir_program(&acir_program); // Transpile to AVM - let avm_bytecode = brillig_to_avm(brillig); + let avm_bytecode = brillig_to_avm(brillig_bytecode); // Push modified function entry to ABI functions.push(AvmOrAcirContractFunction::Avm(AvmContractFunction { diff --git a/avm-transpiler/src/utils.rs b/avm-transpiler/src/utils.rs index 684dde7b6e4..97667a386c0 100644 --- a/avm-transpiler/src/utils.rs +++ b/avm-transpiler/src/utils.rs @@ -1,33 +1,46 @@ use log::debug; -use acvm::acir::circuit::brillig::Brillig; -use acvm::acir::circuit::Opcode; +use acvm::acir::brillig::Opcode as BrilligOpcode; +use acvm::acir::circuit::{Opcode, Program}; use crate::instructions::AvmInstruction; -/// Extract the Brillig program from its ACIR wrapper instruction. -/// An Noir unconstrained function compiles to one ACIR instruction -/// wrapping a Brillig program. This function just extracts that Brillig -/// assuming the 0th ACIR opcode is the wrapper. -pub fn extract_brillig_from_acir(opcodes: &Vec) -> &Brillig { - if opcodes.len() != 1 { - panic!("An AVM program should be contained entirely in only a single ACIR opcode flagged as 'Brillig'"); - } - let opcode = &opcodes[0]; - match opcode { - Opcode::Brillig(brillig) => brillig, +/// Extract the Brillig program from its `Program` wrapper. +/// Noir entry point unconstrained functions are compiled to their own list contained +/// as part of a full program. Function calls are then accessed through a function +/// pointer opcode in ACIR that fetches those unconstrained functions from the main list. +/// This function just extracts Brillig bytecode, with the assumption that the +/// 0th unconstrained function in the full `Program` structure. +pub fn extract_brillig_from_acir_program(program: &Program) -> &[BrilligOpcode] { + assert_eq!( + program.functions.len(), + 1, + "An AVM program should have only a single ACIR function flagged as 'BrilligCall'" + ); + let opcodes = &program.functions[0].opcodes; + assert_eq!( + opcodes.len(), + 1, + "An AVM program should have only a single ACIR function flagged as 'BrilligCall'" + ); + match opcodes[0] { + Opcode::BrilligCall { .. } => {} _ => panic!("Tried to extract a Brillig program from its ACIR wrapper opcode, but the opcode doesn't contain Brillig!"), } + assert_eq!( + program.unconstrained_functions.len(), + 1, + "An AVM program should be contained entirely in only a single `Brillig` function" + ); + &program.unconstrained_functions[0].bytecode } /// Print inputs, outputs, and instructions in a Brillig program -pub fn dbg_print_brillig_program(brillig: &Brillig) { +pub fn dbg_print_brillig_program(brillig_bytecode: &[BrilligOpcode]) { debug!("Printing Brillig program..."); - debug!("\tInputs: {:?}", brillig.inputs); - for (i, instruction) in brillig.bytecode.iter().enumerate() { + for (i, instruction) in brillig_bytecode.iter().enumerate() { debug!("\tPC:{0} {1:?}", i, instruction); } - debug!("\tOutputs: {:?}", brillig.outputs); } /// Print each instruction in an AVM program diff --git a/barretenberg/.gitrepo b/barretenberg/.gitrepo index 27488d86f2f..107719b5a24 100644 --- a/barretenberg/.gitrepo +++ b/barretenberg/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/barretenberg branch = master - commit = b2e6d246e25276e190c3ae8f6895d31f843d498a - parent = 37daac6a4547d70d06714e1cd727eddbe297cf64 + commit = ed310b6d7e43b47913afacb717513cd4ff2d57dd + parent = 3fb94c0cd5ffba20a99b97c0088ae5ef357c205d method = merge cmdver = 0.4.6 diff --git a/boxes/boxes/react/package.json b/boxes/boxes/react/package.json index ea7ded69c00..0cd42e16ae5 100644 --- a/boxes/boxes/react/package.json +++ b/boxes/boxes/react/package.json @@ -7,7 +7,7 @@ "main": "./dist/index.js", "scripts": { "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_CLI:-aztec-cli} codegen src/contracts/target -o artifacts --ts", + "codegen": "${AZTEC_CLI:-aztec-cli} codegen src/contracts/target -o artifacts", "clean": "rm -rf ./dist .tsbuildinfo ./artifacts ./src/contracts/target", "prep": "yarn clean && yarn compile && yarn codegen", "dev": "yarn prep && webpack serve --mode development", diff --git a/boxes/boxes/vanilla/package.json b/boxes/boxes/vanilla/package.json index bed49cf08f8..4e9c549afc6 100644 --- a/boxes/boxes/vanilla/package.json +++ b/boxes/boxes/vanilla/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "compile": "cd src/contracts && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_CLI:-aztec-cli} codegen src/contracts/target -o artifacts --ts", + "codegen": "${AZTEC_CLI:-aztec-cli} codegen src/contracts/target -o artifacts", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./src/contracts/target", "prep": "yarn clean && yarn compile && yarn codegen && tsc -b", "dev": "yarn prep && webpack serve --mode development", diff --git a/boxes/contract-only/package.json b/boxes/contract-only/package.json index 361571253f8..93e8c27ca85 100644 --- a/boxes/contract-only/package.json +++ b/boxes/contract-only/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "compile": "cd src && ${AZTEC_NARGO:-aztec-nargo} compile", - "codegen": "${AZTEC_CLI:-aztec-cli} codegen target -o artifacts --ts", + "codegen": "${AZTEC_CLI:-aztec-cli} codegen target -o artifacts", "clean": "rm -rf ./dest .tsbuildinfo ./artifacts ./target", "prep": "yarn clean && yarn compile && yarn codegen && tsc -b", "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --runInBand", diff --git a/build-system/scripts/deploy_npm b/build-system/scripts/deploy_npm index c4ca396282e..577f074ce09 100755 --- a/build-system/scripts/deploy_npm +++ b/build-system/scripts/deploy_npm @@ -71,3 +71,29 @@ else npm publish $TAG_ARG --access public fi fi + +# Verify deployment +echo "Verifying deployment of version $VERSION with tag $TAG" +END_TIME=$((SECONDS + 300)) # 5 minutes + +while [ $SECONDS -lt $END_TIME ]; do + # Check version and tag + if npm view "$PACKAGE_NAME@$VERSION" version >/dev/null 2>&1; then + # Extract tag info and check + if npm dist-tag ls "$PACKAGE_NAME" | grep -q "$TAG: $VERSION"; then + echo "Version $VERSION with tag $TAG successfully deployed ." + break + else + echo "Version $VERSION is available, but tag $TAG is not correctly set." + fi + else + echo "Waiting for version $VERSION to be available..." + fi + sleep 5 +done + +# Final check to confirm both version and tag are correctly set +if ! npm dist-tag ls "$PACKAGE_NAME" | grep -q "$TAG: $VERSION"; then + echo "Failed to verify the deployment of version $VERSION with tag $TAG within the timeout period." + exit 1 +fi diff --git a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md index 7d78818d4ff..6135b4d8e1a 100644 --- a/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md +++ b/docs/docs/developers/contracts/compiling_contracts/how_to_compile_contract.md @@ -24,10 +24,8 @@ This will output a JSON [artifact](./artifacts.md) for each contract in the proj You can use the code generator to autogenerate type-safe typescript classes for each of your contracts. These classes define type-safe methods for deploying and interacting with your contract based on their artifact. -To generate them, include a `--ts` option in the `codegen` command with a path to the target folder for the typescript files: - ```bash -aztec-cli codegen ./aztec-nargo/output/target/path -o src/artifacts --ts +aztec-cli codegen ./aztec-nargo/output/target/path -o src/artifacts ``` Below is typescript code generated from the [Token](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/noir-contracts/contracts/token_contract/src/main.nr) contract: @@ -119,94 +117,34 @@ Read more about interacting with contracts using `aztec.js` [here](../../getting An Aztec.nr contract can [call a function](../writing_contracts/functions/call_functions.md) in another contract via `context.call_private_function` or `context.call_public_function`. However, this requires manually assembling the function selector and manually serializing the arguments, which is not type-safe. -To make this easier, the compiler can generate contract interface structs that expose a convenience method for each function listed in a given contract artifact. These structs are intended to be used from another contract project that calls into the current one. For each contract, two interface structs are generated: one to be used from private functions with a `PrivateContext`, and one to be used from open functions with a `PublicContext`. - -To generate them, include a `--nr` option in the `codegen` command with a path to the target folder for the generated Aztec.nr interface files: - -```bash -aztec-cli codegen ./aztec-nargo/output/target/path -o ./path/to/output/folder --nr -``` +To make this easier, the compiler automatically generates interface structs that expose a convenience method for each function listed in a given contract artifact. These structs are intended to be used from another contract project that calls into the current one. -Below is an example interface, also generated from the [Token](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/noir-contracts/contracts/token_contract/src/main.nr) contract: +Below is an example of interface usage generated from the [Token](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/noir-contracts/contracts/token_contract/src/main.nr) contract, used from the [FPC](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr): ```rust -impl TokenPrivateContextInterface { - pub fn at(address: Field) -> Self { - Self { - address, - } - } - - pub fn burn( - self, - context: &mut PrivateContext, - from: FromBurnStruct, - amount: Field, - nonce: Field - ) -> [Field; RETURN_VALUES_LENGTH] { - let mut serialized_args = [0; 3]; - serialized_args[0] = from.address; - serialized_args[1] = amount; - serialized_args[2] = nonce; - - context.call_private_function(self.address, 0xd4fcc96e, serialized_args) - } - - - pub fn burn_public( - self, - context: &mut PrivateContext, - from: FromBurnPublicStruct, - amount: Field, - nonce: Field - ) { - let mut serialized_args = [0; 3]; - serialized_args[0] = from.address; - serialized_args[1] = amount; - serialized_args[2] = nonce; +contract FPC { - context.call_public_function(self.address, 0xb0e964d5, serialized_args) - } - ... - -} + ... -impl TokenPublicContextInterface { - pub fn at(address: Field) -> Self { - Self { - address, - } - } + use dep::token::Token; - pub fn burn_public( - self, - context: PublicContext, - from: FromBurnPublicStruct, - amount: Field, - nonce: Field - ) -> [Field; RETURN_VALUES_LENGTH] { - let mut serialized_args = [0; 3]; - serialized_args[0] = from.address; - serialized_args[1] = amount; - serialized_args[2] = nonce; - - context.call_public_function(self.address, 0xb0e964d5, serialized_args) - } + ... - pub fn mint_private( - self, - context: PublicContext, - amount: Field, - secret_hash: Field - ) -> [Field; RETURN_VALUES_LENGTH] { - let mut serialized_args = [0; 2]; - serialized_args[0] = amount; - serialized_args[1] = secret_hash; + #[aztec(private)] + fn fee_entrypoint_private(amount: Field, asset: AztecAddress, secret_hash: Field, nonce: Field) { + assert(asset == storage.other_asset.read_private()); + Token::at(asset).unshield(context.msg_sender(), context.this_address(), amount, nonce).call(&mut context); + FPC::at(context.this_address()).pay_fee_with_shielded_rebate(amount, asset, secret_hash).enqueue(&mut context); + } - context.call_public_function(self.address, 0x10763932, serialized_args) - } + #[aztec(private)] + fn fee_entrypoint_public(amount: Field, asset: AztecAddress, nonce: Field) { + FPC::at(context.this_address()).prepare_fee(context.msg_sender(), amount, asset, nonce).enqueue(&mut context); + FPC::at(context.this_address()).pay_fee(context.msg_sender(), amount, asset).enqueue(&mut context); + } + ... } ``` diff --git a/docs/docs/developers/contracts/deploying_contracts/how_to_deploy_contract.md b/docs/docs/developers/contracts/deploying_contracts/how_to_deploy_contract.md index 2ac74e787e2..dd646d383fb 100644 --- a/docs/docs/developers/contracts/deploying_contracts/how_to_deploy_contract.md +++ b/docs/docs/developers/contracts/deploying_contracts/how_to_deploy_contract.md @@ -40,7 +40,7 @@ aztec-nargo compile Generate the typescript class: ```bash -aztec-cli codegen ./aztec-nargo/output/target/path -o src/artifacts --ts +aztec-cli codegen ./aztec-nargo/output/target/path -o src/artifacts ``` This would create a typescript file like `Example.ts` in `./src/artifacts`. Read more on the [compiling page](../compiling_contracts/how_to_compile_contract.md). diff --git a/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md b/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md index d738af37879..6de1c8abae6 100644 --- a/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md +++ b/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/implement_slow_updates.md @@ -8,25 +8,19 @@ On this page you will learn how to implement a slow updates tree into your contr # How to implement a slow updates tree -1. Copy the _SlowTree.nr_ example and its dependencies, found [here](https://github.com/AztecProtocol/aztec-packages/tree/master/noir-projects/noir-contracts/contracts/slow_tree_contract). Replace the constants with whatever you like and deploy it to your sandbox -2. Copy the _SlowMap interface_ for easy interaction with your deployed SlowTree. Find it [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/interfaces.nr) -3. Import this interface into your contract - -#include_code interface noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust - -5. Store the SlowTree address in private storage as a FieldNote +1. Store the SlowTree address in private storage as a FieldNote #include_code constructor noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust -6. Store the SlowTree address in public storage and initialize an instance of SlowMap using this address +2. Store the SlowTree address in public storage and initialize an instance of SlowMap using this address #include_code write_slow_update_public noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust -7. Now you can read and update from private functions: +3. Now you can read and update from private functions: #include_code get_and_update_private noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust -8. Or from public functions: +4. Or from public functions: #include_code get_public noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr rust diff --git a/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/main.md b/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/main.md index 170981942d9..4edc82d0537 100644 --- a/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/main.md +++ b/docs/docs/developers/contracts/writing_contracts/historical_data/slow_updates_tree/main.md @@ -16,10 +16,6 @@ There are generally 4 main components involved to make it easier to use a slow u This is the primary smart contract that will use the slow updates tree. In the example we use a [token with blacklisting features](./implement_slow_updates.md#exploring-an-example-integration-through-a-tokenblacklist-smart-contract). -## Interface - -This interface of the slow updates tree contract allows your contract to interact with the Slow Updates Tree contract. It provides methods for reading and updating values in the tree in both public and private contexts. You can find it [here](https://github.com/AztecProtocol/aztec-packages/blob/master/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/interfaces.nr). - ## SlowTree.nr contract This is a smart contract developed by Aztec that establishes and manages a slow updates tree structure. It allows developers to access and interact with the tree, such as reading and updating data. diff --git a/docs/docs/developers/getting_started/aztecnr-getting-started.md b/docs/docs/developers/getting_started/aztecnr-getting-started.md index ae8b1e83e23..d7b9dd1eb10 100644 --- a/docs/docs/developers/getting_started/aztecnr-getting-started.md +++ b/docs/docs/developers/getting_started/aztecnr-getting-started.md @@ -147,7 +147,7 @@ This will compile the smart contract and create a `target` folder with a `.json` After compiling, you can generate a typescript class. In the same directory, run this: ```bash -aztec-cli codegen target -o src/artifacts --ts +aztec-cli codegen target -o src/artifacts ``` ### Deploy diff --git a/docs/docs/developers/tutorials/token_portal/minting_on_aztec.md b/docs/docs/developers/tutorials/token_portal/minting_on_aztec.md index 877a507122d..0eb400f0acb 100644 --- a/docs/docs/developers/tutorials/token_portal/minting_on_aztec.md +++ b/docs/docs/developers/tutorials/token_portal/minting_on_aztec.md @@ -12,13 +12,6 @@ In our `token-bridge` Aztec project in `aztec-contracts`, under `src` there is a #include_code token_bridge_storage_and_constructor /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust -This imports Aztec-related dependencies and our helper file `token_interface.nr`. -(The code above will give errors right now - this is because we haven't implemented util and token_interface yet.) - -In `token_interface.nr`, add this: - -#include_code token_bridge_token_interface /noir-projects/noir-contracts/contracts/token_bridge_contract/src/token_interface.nr rust - ## Consume the L1 message In the previous step, we have moved our funds to the portal and created a L1->L2 message. Upon building the next rollup, the sequencer asks the inbox for any incoming messages and adds them to Aztec’s L1->L2 message tree, so an application on L2 can prove that the message exists and consumes it. diff --git a/docs/docs/developers/tutorials/token_portal/setup.md b/docs/docs/developers/tutorials/token_portal/setup.md index 1678df1f98e..8eb45c6d435 100644 --- a/docs/docs/developers/tutorials/token_portal/setup.md +++ b/docs/docs/developers/tutorials/token_portal/setup.md @@ -65,7 +65,7 @@ aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_ token_portal_content_hash_lib = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/contracts/token_portal_content_hash_lib" } ``` -We will also be writing some helper functions that should exist elsewhere so we don't overcomplicated our contract. In `src` create two more files - one called `util.nr` and one called `token_interface` - so your dir structure should now look like this: +We will also be writing some helper functions that should exist elsewhere so we don't overcomplicated our contract. In `src` create one more file called `util.nr` - so your dir structure should now look like this: ```tree aztec-contracts @@ -73,7 +73,6 @@ aztec-contracts ├── Nargo.toml ├── src ├── main.nr - ├── token_interface.nr ├── util.nr ``` diff --git a/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md b/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md index 4e2246e20fb..524e106ef51 100644 --- a/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md +++ b/docs/docs/developers/tutorials/token_portal/withdrawing_to_l1.md @@ -81,7 +81,7 @@ aztec-nargo compile And generate the TypeScript interface for the contract and add it to the test dir: ```bash -aztec-cli codegen target -o ../../src/test/fixtures --ts +aztec-cli codegen target -o ../../src/test/fixtures ``` This will create a TS interface in our `src/test` folder! diff --git a/docs/docs/developers/tutorials/uniswap/setup.md b/docs/docs/developers/tutorials/uniswap/setup.md index a80b63e734a..ba86ecb73be 100644 --- a/docs/docs/developers/tutorials/uniswap/setup.md +++ b/docs/docs/developers/tutorials/uniswap/setup.md @@ -50,6 +50,8 @@ Inside `uniswap/Nargo.toml` paste this in `[dependencies]`: [dependencies] aztec = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/aztec-nr/aztec" } authwit = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/aztec-nr/authwit"} +token = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/token_contract" } +token_bridge = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#include_aztec_version", directory="noir-projects/noir-contracts/token_bridge_contract" } ``` ## L2 contracts @@ -57,18 +59,9 @@ authwit = { git="https://github.com/AztecProtocol/aztec-packages/", tag="#includ The `main.nr` will utilize a few helper functions that are outside the scope of this tutorial. Inside `uniswap/src` create two new files: ```bash -cd uniswap/src && touch util.nr && touch interfaces.nr +cd uniswap/src && touch util.nr ``` -Inside `interfaces.nr` paste this: - -#include_code interfaces noir-projects/noir-contracts/contracts/uniswap_contract/src/interfaces.nr rust - -This creates interfaces for the `Token` contract and `TokenBridge` contract - -- `Token` is a reference implementation for a token on Aztec. Here we just need two methods - [`transfer_public`](../writing_token_contract.md#transfer_public) and [`unshield()`](../writing_token_contract.md#unshield). -- The `TokenBridge` facilitates interactions with our [bridge contract](../token_portal/main.md). Here we just need its [`exit_to_l1_public`](../token_portal/withdrawing_to_l1.md) - ## Run Aztec sandbox You will need a running sandbox. diff --git a/docs/docs/developers/tutorials/uniswap/typescript_glue_code.md b/docs/docs/developers/tutorials/uniswap/typescript_glue_code.md index 805a9249826..2d5d04e4a1b 100644 --- a/docs/docs/developers/tutorials/uniswap/typescript_glue_code.md +++ b/docs/docs/developers/tutorials/uniswap/typescript_glue_code.md @@ -36,7 +36,7 @@ aztec-nargo compile And then generate the typescript interface: ```bash -aztec-cli codegen ./target/ -o ../../../src/test/fixtures uniswap --ts +aztec-cli codegen ./target/ -o ../../../src/test/fixtures uniswap ``` This will create a TS interface in our `src/test` folder that will help us write our test. diff --git a/docs/docs/developers/tutorials/writing_private_voting_contract.md b/docs/docs/developers/tutorials/writing_private_voting_contract.md index 685b89a9412..1178600c72a 100644 --- a/docs/docs/developers/tutorials/writing_private_voting_contract.md +++ b/docs/docs/developers/tutorials/writing_private_voting_contract.md @@ -158,7 +158,7 @@ aztec-nargo compile This will create a new directory called `target` and a JSON artifact inside it. To optionally create a typescript interface, run: ```bash -aztec-cli codegen target -o src/artifacts --ts +aztec-cli codegen target -o src/artifacts ``` Once it is compiled you can [deploy](../contracts/deploying_contracts/how_to_deploy_contract.md) it to the sandbox. Ensure your [sandbox is running](../sandbox/references/sandbox-reference.md) and run this in the same dir as before: diff --git a/docs/docs/developers/tutorials/writing_token_contract.md b/docs/docs/developers/tutorials/writing_token_contract.md index a4f5926c5b5..a9b9e942391 100644 --- a/docs/docs/developers/tutorials/writing_token_contract.md +++ b/docs/docs/developers/tutorials/writing_token_contract.md @@ -431,7 +431,7 @@ aztec-nargo compile Once your contract is compiled, optionally generate a typescript interface with the following command: ```bash -aztec-cli codegen target -o src/artifacts --ts +aztec-cli codegen target -o src/artifacts ``` ## Next Steps diff --git a/docs/docs/misc/migration_notes.md b/docs/docs/misc/migration_notes.md index 8f4f8b84217..5b0a8c0cf29 100644 --- a/docs/docs/misc/migration_notes.md +++ b/docs/docs/misc/migration_notes.md @@ -8,6 +8,54 @@ Aztec is in full-speed development. Literally every version breaks compatibility ## TBD +### [Aztec.nr] Contract interfaces + +It is now possible to import contracts on another contracts and use their automatic interfaces to perform calls. The interfaces have the same name as the contract, and are automatically exported. Parameters are automatically serialized (using the `Serialize` trait) and return values are automatically deserialized (using the `Deserialize` trait). Serialize and Deserialize methods have to conform to the standard ACVM serialization schema for the interface to work! + +1. Only fixed length types are supported +2. All numeric types become Fields +3. Strings become arrays of Fields, one per char +4. Arrays become arrays of Fields following rules 2 and 3 +5. Structs become arrays of Fields, with every item defined in the same order as they are in Noir code, following rules 2, 3, 4 and 5 (recursive) + + +```diff +- context.call_public_function( +- storage.gas_token_address.read_private(), +- FunctionSelector::from_signature("pay_fee(Field)"), +- [42] +- ); +- +- context.call_public_function( +- storage.gas_token_address.read_private(), +- FunctionSelector::from_signature("pay_fee(Field)"), +- [42] +- ); +- +- let _ = context.call_private_function( +- storage.subscription_token_address.read_private(), +- FunctionSelector::from_signature("transfer((Field),(Field),Field,Field)"), +- [ +- context.msg_sender().to_field(), +- storage.subscription_recipient_address.read_private().to_field(), +- storage.subscription_price.read_private(), +- nonce +- ] +- ); ++ use dep::gas_token::GasToken; ++ use dep::token::Token; ++ ++ ... ++ // Public call from public land ++ GasToken::at(storage.gas_token_address.read_private()).pay_fee(42).call(&mut context); ++ // Public call from private land ++ GasToken::at(storage.gas_token_address.read_private()).pay_fee(42).enqueue(&mut context); ++ // Private call from private land ++ Token::at(asset).transfer(context.msg_sender(), storage.subscription_recipient_address.read_private(), amount, nonce).call(&mut context); +``` + +It is also possible to use these automatic interfaces from the local contract, and thus enqueue public calls from private without having to rely on low level `context` calls. + ### [Aztec.nr] Rename max block number setter The `request_max_block_number` function has been renamed to `set_tx_max_block_number` to better reflect that it is not a getter, and that the setting is transaction-wide. diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index fe139215971..ea4ec9cca1c 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -26,6 +26,8 @@ library Constants { uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1; + uint256 internal constant MAX_ENCRYPTED_LOGS_PER_CALL = 4; + uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_CALL = 4; uint256 internal constant MAX_NEW_NOTE_HASHES_PER_TX = 64; uint256 internal constant MAX_NEW_NULLIFIERS_PER_TX = 64; uint256 internal constant MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; @@ -37,8 +39,11 @@ library Constants { uint256 internal constant MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; uint256 internal constant MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; uint256 internal constant MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4; + uint256 internal constant MAX_ENCRYPTED_LOGS_PER_TX = 8; + uint256 internal constant MAX_UNENCRYPTED_LOGS_PER_TX = 8; uint256 internal constant NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; uint256 internal constant NUM_UNENCRYPTED_LOGS_HASHES_PER_TX = 1; + uint256 internal constant MAX_PUBLIC_DATA_HINTS = 64; uint256 internal constant NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; uint256 internal constant VK_TREE_HEIGHT = 3; uint256 internal constant FUNCTION_TREE_HEIGHT = 5; @@ -69,7 +74,7 @@ library Constants { uint256 internal constant INITIAL_L2_BLOCK_NUM = 1; uint256 internal constant BLOB_SIZE_IN_BYTES = 126976; uint256 internal constant NESTED_CALL_L2_GAS_BUFFER = 20000; - uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 16000; + uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 16200; uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 3000; uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS = 3000; uint256 internal constant REGISTERER_PRIVATE_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS = 19; @@ -83,7 +88,7 @@ library Constants { uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; uint256 internal constant DEPLOYER_CONTRACT_ADDRESS = - 0x2d8e7aedc70b65d49e6aa0794d8d12721896c177e87126701f6e60d184358e74; + 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2; uint256 internal constant L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 17; uint256 internal constant MAX_NOTE_FIELDS_LENGTH = 20; uint256 internal constant GET_NOTE_ORACLE_RETURN_LENGTH = 23; @@ -110,9 +115,9 @@ library Constants { uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; uint256 internal constant NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; uint256 internal constant PARTIAL_STATE_REFERENCE_LENGTH = 6; - uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 224; - uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 221; - uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 215; + uint256 internal constant PRIVATE_CALL_STACK_ITEM_LENGTH = 238; + uint256 internal constant PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 235; + uint256 internal constant PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 222; uint256 internal constant STATE_REFERENCE_LENGTH = 8; uint256 internal constant TX_CONTEXT_DATA_LENGTH = 4; uint256 internal constant TX_REQUEST_LENGTH = 18; diff --git a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol index a57d4a26a25..c3f95e61170 100644 --- a/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol +++ b/l1-contracts/src/core/libraries/decoders/TxsDecoder.sol @@ -239,17 +239,21 @@ library TxsDecoder { uint256 privateCircuitPublicInputLogsLength = read4(_body, offset); offset += 0x4; - // Hash the logs of this iteration's function call - bytes32 privateCircuitPublicInputsLogsHash = - Hash.sha256ToField(slice(_body, offset, privateCircuitPublicInputLogsLength)); - offset += privateCircuitPublicInputLogsLength; - // Decrease remaining logs length by this privateCircuitPublicInputsLogs's length (len(I?_LOGS)) and 4 bytes for I?_LOGS_LEN remainingLogsLength -= (privateCircuitPublicInputLogsLength + 0x4); - kernelPublicInputsLogsHash = Hash.sha256ToField( - bytes.concat(kernelPublicInputsLogsHash, privateCircuitPublicInputsLogsHash) - ); + while (privateCircuitPublicInputLogsLength > 0) { + uint256 singleCallLogsLength = read4(_body, offset); + offset += 0x4; + + bytes32 singleLogHash = Hash.sha256ToField(slice(_body, offset, singleCallLogsLength)); + offset += singleCallLogsLength; + + kernelPublicInputsLogsHash = + Hash.sha256ToField(bytes.concat(kernelPublicInputsLogsHash, singleLogHash)); + + privateCircuitPublicInputLogsLength -= (singleCallLogsLength + 0x4); + } } return (kernelPublicInputsLogsHash, offset); diff --git a/l1-contracts/test/decoders/Decoders.t.sol b/l1-contracts/test/decoders/Decoders.t.sol index 3857a9305d0..accec36ab51 100644 --- a/l1-contracts/test/decoders/Decoders.t.sol +++ b/l1-contracts/test/decoders/Decoders.t.sol @@ -180,25 +180,20 @@ contract DecodersTest is DecoderBase { (bytes32 logsHash, uint256 bytesAdvanced) = txsHelper.computeKernelLogsHash(encodedLogs); - bytes32 kernelPublicInputsLogsHash = bytes32(0); - bytes32 privateCircuitPublicInputsLogsHash = Hash.sha256ToField(new bytes(0)); - - bytes32 referenceLogsHash = Hash.sha256ToField( - abi.encodePacked(kernelPublicInputsLogsHash, privateCircuitPublicInputsLogsHash) - ); - assertEq(bytesAdvanced, encodedLogs.length, "Advanced by an incorrect number of bytes"); - assertEq(logsHash, referenceLogsHash, "Incorrect logs hash"); + assertEq(logsHash, bytes32(0), "Incorrect logs hash"); } function testComputeKernelLogs1Iteration() public { // || K_LOGS_LEN | I1_LOGS_LEN | I1_LOGS || // K_LOGS_LEN = 4 + 8 = 12 (hex"0000000c") // I1_LOGS_LEN = 8 (hex"00000008") - // I1_LOGS = 8 bytes (hex"0000000493e78a70") // Note: 00000004 is the length of 1 log within function logs - bytes memory firstFunctionCallLogs = hex"0000000493e78a70"; + // I1_LOGS = 8 bytes (hex"0000000493e78a70") + bytes memory firstFunctionCallLogs = hex"93e78a70"; // Prefix logs with length of kernel logs (12) and length of iteration 1 logs (8) - bytes memory encodedLogs = abi.encodePacked(hex"0000000c00000008", firstFunctionCallLogs); + // Note: 00000004 is the length of 1 log within function logs + bytes memory encodedLogs = + abi.encodePacked(hex"0000000c00000008", hex"00000004", firstFunctionCallLogs); (bytes32 logsHash, uint256 bytesAdvanced) = txsHelper.computeKernelLogsHash(encodedLogs); // Zero because this is the first iteration @@ -222,10 +217,15 @@ contract DecodersTest is DecoderBase { // I1_LOGS = 8 random bytes (hex"0000000493e78a70") // I2_LOGS_LEN = 20 (hex"00000014") // I2_LOGS = 20 bytes (hex"0000001006a86173c86c6d3f108eefc36e7fb014") - bytes memory firstFunctionCallLogs = hex"0000000493e78a70"; - bytes memory secondFunctionCallLogs = hex"0000001006a86173c86c6d3f108eefc36e7fb014"; + bytes memory firstFunctionCallLogs = hex"93e78a70"; + bytes memory secondFunctionCallLogs = hex"06a86173c86c6d3f108eefc36e7fb014"; bytes memory encodedLogs = abi.encodePacked( - hex"0000002400000008", firstFunctionCallLogs, hex"00000014", secondFunctionCallLogs + hex"0000002400000008", + hex"00000004", + firstFunctionCallLogs, + hex"00000014", + hex"00000010", + secondFunctionCallLogs ); (bytes32 logsHash, uint256 bytesAdvanced) = txsHelper.computeKernelLogsHash(encodedLogs); @@ -254,15 +254,17 @@ contract DecodersTest is DecoderBase { // I2_LOGS = 0 bytes (hex"") // I3_LOGS_LEN = 20 (hex"00000014") // I3_LOGS = 20 random bytes (hex"0000001006a86173c86c6d3f108eefc36e7fb014") - bytes memory firstFunctionCallLogs = hex"0000000493e78a70"; + bytes memory firstFunctionCallLogs = hex"93e78a70"; bytes memory secondFunctionCallLogs = hex""; - bytes memory thirdFunctionCallLogs = hex"0000001006a86173c86c6d3f108eefc36e7fb014"; + bytes memory thirdFunctionCallLogs = hex"06a86173c86c6d3f108eefc36e7fb014"; bytes memory encodedLogs = abi.encodePacked( hex"0000002800000008", + hex"00000004", firstFunctionCallLogs, hex"00000000", secondFunctionCallLogs, hex"00000014", + hex"00000010", thirdFunctionCallLogs ); (bytes32 logsHash, uint256 bytesAdvanced) = txsHelper.computeKernelLogsHash(encodedLogs); @@ -270,19 +272,13 @@ contract DecodersTest is DecoderBase { bytes32 referenceLogsHashFromIteration1 = Hash.sha256ToField(abi.encodePacked(bytes32(0), Hash.sha256ToField(firstFunctionCallLogs))); - bytes32 privateCircuitPublicInputsLogsHashSecondCall = - Hash.sha256ToField(secondFunctionCallLogs); - - bytes32 referenceLogsHashFromIteration2 = Hash.sha256ToField( - abi.encodePacked( - referenceLogsHashFromIteration1, privateCircuitPublicInputsLogsHashSecondCall - ) - ); + // Note: as of resolving #5017, we now hash logs inside the circuits + // Following the YP, we skip any zero length logs, hence no use of secondFunctionCallLogs here bytes32 privateCircuitPublicInputsLogsHashThirdCall = Hash.sha256ToField(thirdFunctionCallLogs); bytes32 referenceLogsHashFromIteration3 = Hash.sha256ToField( - abi.encodePacked(referenceLogsHashFromIteration2, privateCircuitPublicInputsLogsHashThirdCall) + abi.encodePacked(referenceLogsHashFromIteration1, privateCircuitPublicInputsLogsHashThirdCall) ); assertEq(bytesAdvanced, encodedLogs.length, "Advanced by an incorrect number of bytes"); diff --git a/l1-contracts/test/fixtures/empty_block_0.json b/l1-contracts/test/fixtures/empty_block_0.json index fc35e30bee6..16e7729fc67 100644 --- a/l1-contracts/test/fixtures/empty_block_0.json +++ b/l1-contracts/test/fixtures/empty_block_0.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x2ea0c3d3ffef649532de4fb75c9135681ef65b926876b5ff37a4bacfb679f558", + "archive": "0x2683d379c0ad62e225372f35b74366d8c3cd145a12dbbb2028456da89f889be1", "body": "0x00000000", "txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896", "decodedHeader": { @@ -23,8 +23,8 @@ "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0xf6a7844f33ced45fbfeaa9ba463a706b30d4c454", - "feeRecipient": "0x115f6d9664fe6497dec1741573007fcd96fc24124e05b2d415fe4e43e0de4d6e", + "coinbase": "0xd70b960abd35f82aac6df2d1ca6617b5bcd95ba5", + "feeRecipient": "0x0c67b9f94de6beccefc03b63ba448b53464348836ef20b3e6183c5d4f85653ee", "gasFees": { "feePerDaGas": 0, "feePerL1Gas": 0, @@ -56,8 +56,8 @@ } } }, - "header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db800000001000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000f6a7844f33ced45fbfeaa9ba463a706b30d4c454115f6d9664fe6497dec1741573007fcd96fc24124e05b2d415fe4e43e0de4d6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x000150a504a83df5a4a24f26081fb7397809f2ef5976b687fbdeefb5d42da7f3", + "header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db800000001000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000d70b960abd35f82aac6df2d1ca6617b5bcd95ba50c67b9f94de6beccefc03b63ba448b53464348836ef20b3e6183c5d4f85653ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00ee6ce1f8afb6a9d9da7165bbff8d03d3f2e4ae6a65a9265ecbb7c600244a9c", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 11c88bc30d0..6eb046a8035 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x20411bada543bf4a76e1e2b96c15059c7c81b81b4dec36b15102bcc72dfdebff", + "archive": "0x0be67a10fc9ab9372e7fdfa4fcce95a3ed24d42fb6694ffcd3d418d504d8fef4", "body": "0x00000000", "txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896", "decodedHeader": { @@ -21,10 +21,10 @@ "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1712782698, + "timestamp": 1712912168, "version": 1, - "coinbase": "0xf6a7844f33ced45fbfeaa9ba463a706b30d4c454", - "feeRecipient": "0x115f6d9664fe6497dec1741573007fcd96fc24124e05b2d415fe4e43e0de4d6e", + "coinbase": "0xd70b960abd35f82aac6df2d1ca6617b5bcd95ba5", + "feeRecipient": "0x0c67b9f94de6beccefc03b63ba448b53464348836ef20b3e6183c5d4f85653ee", "gasFees": { "feePerDaGas": 0, "feePerL1Gas": 0, @@ -33,7 +33,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x2ea0c3d3ffef649532de4fb75c9135681ef65b926876b5ff37a4bacfb679f558" + "root": "0x2683d379c0ad62e225372f35b74366d8c3cd145a12dbbb2028456da89f889be1" }, "stateReference": { "l1ToL2MessageTree": { @@ -56,8 +56,8 @@ } } }, - "header": "0x2ea0c3d3ffef649532de4fb75c9135681ef65b926876b5ff37a4bacfb679f55800000002000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006616fd6af6a7844f33ced45fbfeaa9ba463a706b30d4c454115f6d9664fe6497dec1741573007fcd96fc24124e05b2d415fe4e43e0de4d6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00da6d809b78297d6f97202d0679da5a45cfbc2c6594eaeb3f0ac4deba7c6b2e", + "header": "0x2683d379c0ad62e225372f35b74366d8c3cd145a12dbbb2028456da89f889be100000002000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006618f728d70b960abd35f82aac6df2d1ca6617b5bcd95ba50c67b9f94de6beccefc03b63ba448b53464348836ef20b3e6183c5d4f85653ee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00bb8af4db44612602143f2507b6f07f4dc5fdede045494a1467c4bea354bcae", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_0.json b/l1-contracts/test/fixtures/mixed_block_0.json index eeb338cc7ec..ad43a849a54 100644 --- a/l1-contracts/test/fixtures/mixed_block_0.json +++ b/l1-contracts/test/fixtures/mixed_block_0.json @@ -34,7 +34,7 @@ ] }, "block": { - "archive": "0x198e7398bee770978f22a61c05397f4a663b8a1068051fac5173236bfbc3c853", + "archive": "0x195de7b601a7882443a8b98043c504ef921f11a94dfa17ce1f5bc4461c685877", "body": "0x0000000400400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e0200000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000341200000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f0000000000000000000000000000000000000000000000000000000000000569000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be0200000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000381200000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a90000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0200000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c12000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e9000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e0200000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000401200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000", "txsEffectsHash": "0x0097a976d5a0b2aa3ea4f9a657d4a8534ed793f49287da441c5d301adfd10d2a", "decodedHeader": { @@ -49,8 +49,8 @@ "chainId": 31337, "timestamp": 0, "version": 1, - "coinbase": "0xfefb7bf9e18d6ebc9e57c5382f9b2708ad0225d5", - "feeRecipient": "0x26a12e4e18661b750e93a1b2a0ee5ab12232135ea95cf6616fae8e8d9616f169", + "coinbase": "0xcb433ad76e9fe9c41059c27d265df41d9acbf5ff", + "feeRecipient": "0x232da3781f3971d8f6cb0246fd911a893453ef41346cbc81b495f4d887f9a1e3", "gasFees": { "feePerDaGas": 0, "feePerL1Gas": 0, @@ -82,8 +82,8 @@ } } }, - "header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db80000000100000000000000000000000000000000000000000000000000000000000000020097a976d5a0b2aa3ea4f9a657d4a8534ed793f49287da441c5d301adfd10d2a00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00198704eb051da0e43ff1a9b3285f168389ba3dd93f8ec1f75f6cafcadbaeb61864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a20000018028d06967b6a4a1cc3c799fb6f008b63a2ffecd5034b81aa10792a6659f8aca22000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000fefb7bf9e18d6ebc9e57c5382f9b2708ad0225d526a12e4e18661b750e93a1b2a0ee5ab12232135ea95cf6616fae8e8d9616f169000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00444e4b646e6d848f610abdb4b1c5d019b47e10da1d0f16d01f52c4fabda4a9", + "header": "0x05b0b6df52f1d47d0406318558052c89a174fbc9d615def82b3cc9ccc1937db80000000100000000000000000000000000000000000000000000000000000000000000020097a976d5a0b2aa3ea4f9a657d4a8534ed793f49287da441c5d301adfd10d2a00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00198704eb051da0e43ff1a9b3285f168389ba3dd93f8ec1f75f6cafcadbaeb61864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a20000018028d06967b6a4a1cc3c799fb6f008b63a2ffecd5034b81aa10792a6659f8aca22000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000cb433ad76e9fe9c41059c27d265df41d9acbf5ff232da3781f3971d8f6cb0246fd911a893453ef41346cbc81b495f4d887f9a1e3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00e815938884265d230edf2de3b24aa1a8edf2e7fc0fcb65ed15cc6464a33afd", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index 43f83bab720..bfae6182e66 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -34,7 +34,7 @@ ] }, "block": { - "archive": "0x15a231eb83543ddaf08fe316b80e48e50b065b7038ad4d9fec6465d060d7a300", + "archive": "0x1935c3506395eb1b6bc63839e01cd3aa2ca13a5b4ee3de54a1d42dcb00a7f856", "body": "0x0000000400400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e0200000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000441200000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f0000000000000000000000000000000000000000000000000000000000000669000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be0200000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000481200000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a90000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0200000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c12000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e9000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e0200000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000501200000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000", "txsEffectsHash": "0x001f86cec051421edd80056cd49b7bf9034751ec5b14e4c120fdc4427f5bba63", "decodedHeader": { @@ -47,10 +47,10 @@ "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1712782671, + "timestamp": 1712912131, "version": 1, - "coinbase": "0xfefb7bf9e18d6ebc9e57c5382f9b2708ad0225d5", - "feeRecipient": "0x26a12e4e18661b750e93a1b2a0ee5ab12232135ea95cf6616fae8e8d9616f169", + "coinbase": "0xcb433ad76e9fe9c41059c27d265df41d9acbf5ff", + "feeRecipient": "0x232da3781f3971d8f6cb0246fd911a893453ef41346cbc81b495f4d887f9a1e3", "gasFees": { "feePerDaGas": 0, "feePerL1Gas": 0, @@ -59,7 +59,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x198e7398bee770978f22a61c05397f4a663b8a1068051fac5173236bfbc3c853" + "root": "0x195de7b601a7882443a8b98043c504ef921f11a94dfa17ce1f5bc4461c685877" }, "stateReference": { "l1ToL2MessageTree": { @@ -82,8 +82,8 @@ } } }, - "header": "0x198e7398bee770978f22a61c05397f4a663b8a1068051fac5173236bfbc3c853000000020000000000000000000000000000000000000000000000000000000000000002001f86cec051421edd80056cd49b7bf9034751ec5b14e4c120fdc4427f5bba6300212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700a5a7c9f331ce6832a69dc81873ed87de7ceeaaed2af1d595cb14ca9616eddd2e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802ecba8caa69552bb0d9bdf0d13eb328aeb6f166a1509678d9bfa9970971d69ab000001400000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006616fd4ffefb7bf9e18d6ebc9e57c5382f9b2708ad0225d526a12e4e18661b750e93a1b2a0ee5ab12232135ea95cf6616fae8e8d9616f169000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x0020765dfc22a0d3f412276926b1c45f6b5edd0101697be96bbe30938603df6d", + "header": "0x195de7b601a7882443a8b98043c504ef921f11a94dfa17ce1f5bc4461c685877000000020000000000000000000000000000000000000000000000000000000000000002001f86cec051421edd80056cd49b7bf9034751ec5b14e4c120fdc4427f5bba6300212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700a5a7c9f331ce6832a69dc81873ed87de7ceeaaed2af1d595cb14ca9616eddd2e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802ecba8caa69552bb0d9bdf0d13eb328aeb6f166a1509678d9bfa9970971d69ab000001400000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006618f703cb433ad76e9fe9c41059c27d265df41d9acbf5ff232da3781f3971d8f6cb0246fd911a893453ef41346cbc81b495f4d887f9a1e3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0018e52830d20f62abe9ccc5b87f998f69f73a0947b789bed500cb90da337d39", "numTxs": 4 } } \ No newline at end of file diff --git a/noir-projects/aztec-nr/.gitrepo b/noir-projects/aztec-nr/.gitrepo index 8e79a269c16..a2e45aaf6bc 100644 --- a/noir-projects/aztec-nr/.gitrepo +++ b/noir-projects/aztec-nr/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/AztecProtocol/aztec-nr branch = master - commit = 28ec9ab7a3430095c0b615ef097362c9860dac3e + commit = b3b3b3c175697928e729895da32681c72e08912b method = merge cmdver = 0.4.6 - parent = a51c725ab39fc2fe436e1be0d19c37866c7caa2e + parent = b8d73dd57ffae1c5b63cb4bd7364c2038af49f50 diff --git a/noir-projects/aztec-nr/authwit/src/auth.nr b/noir-projects/aztec-nr/authwit/src/auth.nr index 643f725e2f2..55c15acec77 100644 --- a/noir-projects/aztec-nr/authwit/src/auth.nr +++ b/noir-projects/aztec-nr/authwit/src/auth.nr @@ -37,7 +37,7 @@ pub fn assert_current_call_valid_authwit_public( context, on_behalf_of, function_selector, - [inner_hash], + [inner_hash].as_slice(), GasOpts::default() ).deserialize_into(); assert(result == IS_VALID_SELECTOR, "Message not authorized by account"); diff --git a/noir-projects/aztec-nr/aztec/src/context.nr b/noir-projects/aztec-nr/aztec/src/context.nr index 2b546b1e411..c7d79f2e24b 100644 --- a/noir-projects/aztec-nr/aztec/src/context.nr +++ b/noir-projects/aztec-nr/aztec/src/context.nr @@ -7,7 +7,10 @@ mod avm_context; mod interface; mod gas; -use interface::ContextInterface; +use interface::{ + ContextInterface, PrivateCallInterface, PublicCallInterface, PrivateVoidCallInterface, + PublicVoidCallInterface, AvmCallInterface, AvmVoidCallInterface +}; use private_context::PrivateContext; use private_context::PackedReturns; use public_context::PublicContext; diff --git a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr index 0446511184d..c4a6350af39 100644 --- a/noir-projects/aztec-nr/aztec/src/context/avm_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/avm_context.nr @@ -1,3 +1,4 @@ +use crate::hash::{compute_secret_hash, compute_message_hash, compute_message_nullifier}; use dep::protocol_types::{ address::{AztecAddress, EthAddress}, constants::{L1_TO_L2_MESSAGE_LENGTH, NESTED_CALL_L2_GAS_BUFFER}, header::Header @@ -40,7 +41,7 @@ impl AvmContext { * Should be automatically convertible to [Field; N]. For example str works with * one char per field. Otherwise you can use CompressedString. */ - pub fn accumulate_unencrypted_logs(&mut self, event_selector: Field, log: T) { + pub fn emit_unencrypted_log(&mut self, event_selector: Field, log: T) { emit_unencrypted_log(event_selector, log); } pub fn note_hash_exists(self, note_hash: Field, leaf_index: Field) -> bool { @@ -50,32 +51,32 @@ impl AvmContext { l1_to_l2_msg_exists(msg_hash, msg_leaf_index) == 1 } - fn call_public_function_raw( + fn call_public_function_raw( self: &mut Self, gas: GasOpts, contract_address: AztecAddress, temporary_function_selector: Field, - args: [Field; ARGS_COUNT] + args: [Field] ) -> ([Field; RET_COUNT], u8) { call( gas_for_call(gas), contract_address, - args.as_slice(), + args, temporary_function_selector ) } - fn static_call_public_function_raw( + fn static_call_public_function_raw( self: &mut Self, gas: GasOpts, contract_address: AztecAddress, temporary_function_selector: Field, - args: [Field; ARGS_COUNT] + args: [Field] ) -> ([Field; RET_COUNT], u8) { call_static( gas_for_call(gas), contract_address, - args.as_slice(), + args, temporary_function_selector ) } @@ -119,34 +120,49 @@ impl PublicContextInterface for AvmContext { nullifier_exists(unsiloed_nullifier, address.to_field()) == 1 } - fn accumulate_encrypted_logs(&mut self, log: [Field; N]) { - assert(false, "'accumulate_encrypted_logs' not implemented!"); + fn emit_unencrypted_log(&mut self, log: T) { + let event_selector = 0; + self.emit_unencrypted_log(event_selector, log); } - fn accumulate_unencrypted_logs(&mut self, log: T) { - let event_selector = 0; - self.accumulate_unencrypted_logs(event_selector, log); + fn push_unencrypted_log(&mut self, log_hash: Field) { + assert(false, "'push_unencrypted_log' not required for avm - use emit_unencrypted_log!"); } - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) { - assert(false, "'consume_l1_to_l2_message' not implemented!"); + fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field) { + let secret_hash = compute_secret_hash(secret); + let message_hash = compute_message_hash( + sender, + self.chain_id(), + /*recipient=*/self.this_address(), + self.version(), + content, + secret_hash + ); + let nullifier = compute_message_nullifier(message_hash, secret, leaf_index); + + assert(!self.nullifier_exists(nullifier, self.this_address()), "L1-to-L2 message is already nullified"); + assert(self.l1_to_l2_msg_exists(message_hash, leaf_index), "Tried to consume nonexistent L1-to-L2 message"); + + // Push nullifier (and the "commitment" corresponding to this can be "empty") + self.push_new_nullifier(nullifier, 0); } fn message_portal(&mut self, recipient: EthAddress, content: Field) { send_l2_to_l1_msg(recipient, content); } - fn call_public_function( + fn call_public_function( self: &mut Self, contract_address: AztecAddress, temporary_function_selector: FunctionSelector, - args: [Field; ARGS_COUNT], + args: [Field], gas_opts: GasOpts ) -> FunctionReturns { let results = call( gas_for_call(gas_opts), contract_address, - args.as_slice(), + args, temporary_function_selector.to_field() ); let data_to_return: [Field; RETURNS_COUNT] = results.0; @@ -156,17 +172,17 @@ impl PublicContextInterface for AvmContext { FunctionReturns::new(data_to_return) } - fn static_call_public_function( + fn static_call_public_function( self: &mut Self, contract_address: AztecAddress, temporary_function_selector: FunctionSelector, - args: [Field; ARGS_COUNT], + args: [Field], gas_opts: GasOpts ) -> FunctionReturns { let (data_to_return, success): ([Field; RETURNS_COUNT], u8) = call_static( gas_for_call(gas_opts), contract_address, - args.as_slice(), + args, temporary_function_selector.to_field() ); @@ -174,11 +190,11 @@ impl PublicContextInterface for AvmContext { FunctionReturns::new(data_to_return) } - fn delegate_call_public_function( + fn delegate_call_public_function( self: &mut Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field; ARGS_COUNT] + args: [Field] ) -> FunctionReturns { assert(false, "'delegate_call_public_function' not implemented!"); FunctionReturns::new([0; RETURNS_COUNT]) diff --git a/noir-projects/aztec-nr/aztec/src/context/interface.nr b/noir-projects/aztec-nr/aztec/src/context/interface.nr index ef64964368c..a076158d71d 100644 --- a/noir-projects/aztec-nr/aztec/src/context/interface.nr +++ b/noir-projects/aztec-nr/aztec/src/context/interface.nr @@ -1,5 +1,11 @@ -use dep::protocol_types::{abis::function_selector::FunctionSelector, address::{AztecAddress, EthAddress}, header::Header}; +use dep::protocol_types::{ + abis::function_selector::FunctionSelector, address::{AztecAddress, EthAddress}, header::Header, + traits::Deserialize +}; +use crate::context::private_context::PrivateContext; +use crate::context::public_context::PublicContext; +use crate::context::avm_context::AvmContext; use crate::context::gas::GasOpts; use crate::context::public_context::FunctionReturns; @@ -27,28 +33,228 @@ trait PublicContextInterface { fn fee_per_l1_gas(self) -> Field; fn fee_per_l2_gas(self) -> Field; fn message_portal(&mut self, recipient: EthAddress, content: Field); - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress); - fn accumulate_encrypted_logs(&mut self, log: [Field; N]); - fn accumulate_unencrypted_logs(&mut self, log: T); - fn call_public_function( + fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field); + fn emit_unencrypted_log(&mut self, log: T); + // TODO(1165) Merge push_unencrypted_log into emit_unencrypted_log, since oracle call + // in PublicContext will no longer be needed for extracting log hash + fn push_unencrypted_log(&mut self, log_hash: Field); + fn call_public_function( self: &mut Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field; ARGS_COUNT], + args: [Field], gas_opts: GasOpts ) -> FunctionReturns; - fn static_call_public_function( + fn static_call_public_function( self: &mut Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field; ARGS_COUNT], + args: [Field], gas_opts: GasOpts ) -> FunctionReturns; - fn delegate_call_public_function( + fn delegate_call_public_function( self: &mut Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field; ARGS_COUNT] + args: [Field] ) -> FunctionReturns; fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool; } + +struct PrivateCallInterface { + target_contract: AztecAddress, + selector: FunctionSelector, + args_hash: Field, +} + +impl PrivateCallInterface { + pub fn call(self, context: &mut PrivateContext) -> T where T: Deserialize { + let returns = context.call_private_function_with_packed_args( + self.target_contract, + self.selector, + self.args_hash, + false, + false + ); + let unpacked: T = returns.unpack_into(); + unpacked + } + + pub fn static_call(self, context: &mut PrivateContext) -> T where T: Deserialize { + let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false); + returns.unpack_into() + } + + pub fn delegate_call(self, context: &mut PrivateContext) -> T where T: Deserialize { + let returns = context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true); + returns.unpack_into() + } +} + +struct PrivateVoidCallInterface { + target_contract: AztecAddress, + selector: FunctionSelector, + args_hash: Field, +} + +impl PrivateVoidCallInterface { + pub fn call(self, context: &mut PrivateContext) { + context.call_private_function_with_packed_args( + self.target_contract, + self.selector, + self.args_hash, + false, + false + ).assert_empty(); + } + + pub fn static_call(self, context: &mut PrivateContext) { + context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty(); + } + + pub fn delegate_call(self, context: &mut PrivateContext) { + context.call_private_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true).assert_empty(); + } +} + +struct PublicCallInterface { + target_contract: AztecAddress, + selector: FunctionSelector, + args_hash: Field, +} + +impl PublicCallInterface { + + pub fn call(self, context: &mut PublicContext) -> T where T: Deserialize { + let returns = context.call_public_function_with_packed_args( + self.target_contract, + self.selector, + self.args_hash, + false, + false + ); + returns.deserialize_into() + } + + pub fn static_call(self, context: &mut PublicContext) -> T where T: Deserialize { + let returns = context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false); + returns.deserialize_into() + } + + pub fn delegate_call(self, context: &mut PublicContext) -> T where T: Deserialize { + let returns = context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true); + returns.deserialize_into() + } + + pub fn enqueue(self, context: &mut PrivateContext) { + context.call_public_function_with_packed_args( + self.target_contract, + self.selector, + self.args_hash, + false, + false + ) + } + + pub fn static_enqueue(self, context: &mut PrivateContext) { + context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false) + } + + pub fn delegate_enqueue(self, context: &mut PrivateContext) { + context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true) + } +} + +struct PublicVoidCallInterface { + target_contract: AztecAddress, + selector: FunctionSelector, + args_hash: Field +} + +impl PublicVoidCallInterface { + pub fn call(self, context: &mut PublicContext) { + context.call_public_function_with_packed_args( + self.target_contract, + self.selector, + self.args_hash, + false, + false + ).assert_empty() + } + + pub fn static_call(self, context: &mut PublicContext) { + context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false).assert_empty(); + } + + pub fn delegate_call(self, context: &mut PublicContext) { + context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true).assert_empty(); + } + + pub fn enqueue(self, context: &mut PrivateContext) { + context.call_public_function_with_packed_args( + self.target_contract, + self.selector, + self.args_hash, + false, + false + ) + } + + pub fn static_enqueue(self, context: &mut PrivateContext) { + context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, true, false) + } + + pub fn delegate_enqueue(self, context: &mut PrivateContext) { + context.call_public_function_with_packed_args(self.target_contract, self.selector, self.args_hash, false, true) + } +} + +struct AvmCallInterface { + target_contract: AztecAddress, + selector: FunctionSelector, + args: [Field], +} + +impl AvmCallInterface { + pub fn call(self, context: &mut AvmContext, gas_opts: GasOpts) -> T where T: Deserialize { + let returns = context.call_public_function(self.target_contract, self.selector, self.args, gas_opts); + returns.deserialize_into() + } + + pub fn static_call( + self, + context: &mut AvmContext, + gas_opts: GasOpts + ) -> T where T: Deserialize { + let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, gas_opts); + returns.deserialize_into() + } + + pub fn delegate_call(self, context: &mut AvmContext) -> T where T: Deserialize { + let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args); + returns.deserialize_into() + } +} + +struct AvmVoidCallInterface { + target_contract: AztecAddress, + selector: FunctionSelector, + args: [Field], +} + +impl AvmVoidCallInterface { + pub fn call(self, context: &mut AvmContext, gas_opts: GasOpts) { + let returns = context.call_public_function(self.target_contract, self.selector, self.args, gas_opts); + returns.assert_empty() + } + + pub fn static_call(self, context: &mut AvmContext, gas_opts: GasOpts) { + let returns = context.static_call_public_function(self.target_contract, self.selector, self.args, gas_opts); + returns.assert_empty() + } + + pub fn delegate_call(self, context: &mut AvmContext) { + let returns = context.delegate_call_public_function(self.target_contract, self.selector, self.args); + returns.assert_empty() + } +} diff --git a/noir-projects/aztec-nr/aztec/src/context/private_context.nr b/noir-projects/aztec-nr/aztec/src/context/private_context.nr index b70680db040..0c744e60d32 100644 --- a/noir-projects/aztec-nr/aztec/src/context/private_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/private_context.nr @@ -25,7 +25,8 @@ use dep::protocol_types::{ MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL + MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, + MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, grumpkin_private_key::GrumpkinPrivateKey, header::Header, @@ -65,6 +66,8 @@ struct PrivateContext { historical_header: Header, // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, // encrypted_logs_preimages: Vec, // unencrypted_logs_preimages: Vec, @@ -137,6 +140,8 @@ impl PrivateContext { public_call_stack_hashes: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) + encrypted_logs_hashes: BoundedVec::new(), + unencrypted_logs_hashes: BoundedVec::new(), // encrypted_logs_preimages: Vec::new(), // unencrypted_logs_preimages: Vec::new(), nullifier_key: Option::none() @@ -162,8 +167,6 @@ impl PrivateContext { pub fn finish(self) -> PrivateCircuitPublicInputs { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) - let encrypted_logs_hash = 0; - let unencrypted_logs_hash = 0; let encrypted_log_preimages_length = 0; let unencrypted_log_preimages_length = 0; @@ -183,8 +186,8 @@ impl PrivateContext { new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, start_side_effect_counter: self.inputs.start_side_effect_counter, end_side_effect_counter: self.side_effect_counter, - encrypted_logs_hash, - unencrypted_logs_hash, + encrypted_logs_hashes: self.encrypted_logs_hashes.storage, + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length, unencrypted_log_preimages_length, historical_header: self.historical_header, @@ -263,15 +266,17 @@ impl PrivateContext { } // docs:end:consume_l1_to_l2_message - pub fn accumulate_encrypted_logs(&mut self, log: [Field; N]) { - let _void1 = self.inputs; - let _void2 = log; + pub fn push_encrypted_log(&mut self, log_hash: Field) { + let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; + self.encrypted_logs_hashes.push(side_effect); + self.side_effect_counter = self.side_effect_counter + 1; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) } - pub fn accumulate_unencrypted_logs(&mut self, log: T) { - let _void1 = self.inputs; - let _void2 = log; + pub fn push_unencrypted_log(&mut self, log_hash: Field) { + let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; + self.unencrypted_logs_hashes.push(side_effect); + self.side_effect_counter = self.side_effect_counter + 1; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) } @@ -282,7 +287,7 @@ impl PrivateContext { args: [Field; ARGS_COUNT] ) -> PackedReturns { let args_hash = hash_args_array(args); - assert(args_hash == arguments::pack_arguments(args)); + assert(args_hash == arguments::pack_arguments_array(args)); self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, false) } @@ -293,7 +298,7 @@ impl PrivateContext { args: [Field; ARGS_COUNT] ) -> PackedReturns { let args_hash = hash_args_array(args); - assert(args_hash == arguments::pack_arguments(args)); + assert(args_hash == arguments::pack_arguments_array(args)); self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, true, false) } @@ -304,7 +309,7 @@ impl PrivateContext { args: [Field; ARGS_COUNT] ) -> PackedReturns { let args_hash = hash_args_array(args); - assert(args_hash == arguments::pack_arguments(args)); + assert(args_hash == arguments::pack_arguments_array(args)); self.call_private_function_with_packed_args(contract_address, function_selector, args_hash, false, true) } @@ -402,7 +407,7 @@ impl PrivateContext { args: [Field; ARGS_COUNT] ) { let args_hash = hash_args_array(args); - assert(args_hash == arguments::pack_arguments(args)); + assert(args_hash == arguments::pack_arguments_array(args)); self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false) } @@ -413,7 +418,7 @@ impl PrivateContext { args: [Field; ARGS_COUNT] ) { let args_hash = hash_args_array(args); - assert(args_hash == arguments::pack_arguments(args)); + assert(args_hash == arguments::pack_arguments_array(args)); self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false) } @@ -424,7 +429,7 @@ impl PrivateContext { args: [Field; ARGS_COUNT] ) { let args_hash = hash_args_array(args); - assert(args_hash == arguments::pack_arguments(args)); + assert(args_hash == arguments::pack_arguments_array(args)); self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true) } @@ -491,7 +496,7 @@ impl PrivateContext { new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter: 0, end_side_effect_counter: 0, - unencrypted_logs_hash: 0, + unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], unencrypted_log_preimages_length: 0, historical_header: Header::empty(), prover_address: AztecAddress::zero(), @@ -551,6 +556,8 @@ impl Empty for PrivateContext { public_call_stack_hashes : BoundedVec::new(), new_l2_to_l1_msgs : BoundedVec::new(), historical_header: Header::empty(), + encrypted_logs_hashes: BoundedVec::new(), + unencrypted_logs_hashes: BoundedVec::new(), nullifier_key: Option::none(), } } diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 1c61e53712e..ba70631a79f 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -5,7 +5,7 @@ use crate::{ }, messaging::process_l1_to_l2_message, oracle::{arguments, public_call::call_public_function_internal, returns}, - hash::{hash_args_array, ArgsHasher} + hash::{hash_args, ArgsHasher} }; use dep::protocol_types::{ abis::{ @@ -20,7 +20,8 @@ use dep::protocol_types::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL + MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, + MAX_UNENCRYPTED_LOGS_PER_CALL }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, header::Header, messaging::l2_to_l1_message::L2ToL1Message, utils::reader::Reader, traits::{Deserialize, Empty} @@ -44,7 +45,7 @@ struct PublicContext { new_l2_to_l1_msgs: BoundedVec, - unencrypted_logs_hash: Field, + unencrypted_logs_hashes: BoundedVec, unencrypted_logs_preimages_length: Field, // Header of a block whose state is used during public execution. Set by sequencer to be a header of a block @@ -68,7 +69,7 @@ impl PublicContext { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), - unencrypted_logs_hash: 0, + unencrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_preimages_length: 0, historical_header: inputs.historical_header, prover_address: AztecAddress::zero() // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) @@ -146,7 +147,6 @@ impl PublicContext { pub fn finish(self) -> PublicCircuitPublicInputs { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) - let unencrypted_logs_hash = 0; let unencrypted_log_preimages_length = 0; // Compute the public call stack hashes @@ -164,7 +164,7 @@ impl PublicContext { new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, start_side_effect_counter: self.inputs.start_side_effect_counter, end_side_effect_counter: self.side_effect_counter, - unencrypted_logs_hash, + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, unencrypted_log_preimages_length, historical_header: self.inputs.historical_header, prover_address: self.prover_address, @@ -263,7 +263,8 @@ impl PublicContextInterface for PublicContext { // We can consume message with a secret in public context because the message cannot be modified and therefore // there is no front-running risk (e.g. somebody could front run you to claim your tokens to your address). - fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress) { + // Leaf index is not used in public context, but it is used in the AVMContext which will replace it. + fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, _leaf_index: Field) { let this = (*self).this_address(); let nullifier = process_l1_to_l2_message( self.historical_header.state.l1_to_l2_message_tree.root, @@ -279,49 +280,52 @@ impl PublicContextInterface for PublicContext { self.push_new_nullifier(nullifier, 0) } - fn accumulate_encrypted_logs(&mut self, log: [Field; N]) { + fn emit_unencrypted_log(&mut self, log: T) { let _void1 = self; let _void2 = log; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) + // Once we hash inside circuits, this replaces push_unencrypted_log + // For now we need an oracle to get the hash } - fn accumulate_unencrypted_logs(&mut self, log: T) { - let _void1 = self; - let _void2 = log; + fn push_unencrypted_log(&mut self, log_hash: Field) { + let side_effect = SideEffect { value: log_hash, counter: self.side_effect_counter }; + self.unencrypted_logs_hashes.push(side_effect); + self.side_effect_counter = self.side_effect_counter + 1; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) } - fn call_public_function( + fn call_public_function( self: &mut Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field; ARGS_COUNT], + args: [Field], _gas: GasOpts ) -> FunctionReturns { - let args_hash = hash_args_array(args); + let args_hash = hash_args(args); assert(args_hash == arguments::pack_arguments(args)); self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, false) } - fn static_call_public_function( + fn static_call_public_function( self: &mut Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field; ARGS_COUNT], + args: [Field], _gas: GasOpts ) -> FunctionReturns { - let args_hash = hash_args_array(args); + let args_hash = hash_args(args); assert(args_hash == arguments::pack_arguments(args)); self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, true, false) } - fn delegate_call_public_function( + fn delegate_call_public_function( self: &mut Self, contract_address: AztecAddress, function_selector: FunctionSelector, - args: [Field; ARGS_COUNT] + args: [Field] ) -> FunctionReturns { - let args_hash = hash_args_array(args); + let args_hash = hash_args(args); assert(args_hash == arguments::pack_arguments(args)); self.call_public_function_with_packed_args(contract_address, function_selector, args_hash, false, true) } @@ -342,7 +346,7 @@ impl Empty for PublicContext { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), - unencrypted_logs_hash: 0, + unencrypted_logs_hashes: BoundedVec::new(), unencrypted_logs_preimages_length: 0, historical_header: Header::empty(), prover_address: AztecAddress::zero(), diff --git a/noir-projects/aztec-nr/aztec/src/log.nr b/noir-projects/aztec-nr/aztec/src/log.nr index 033db50e09d..0334f1407a7 100644 --- a/noir-projects/aztec-nr/aztec/src/log.nr +++ b/noir-projects/aztec-nr/aztec/src/log.nr @@ -10,21 +10,21 @@ pub fn emit_encrypted_log( encryption_pub_key: GrumpkinPoint, log: [Field; N] ) { - let _ = oracle::logs::emit_encrypted_log( + let log_hash = oracle::logs::emit_encrypted_log( contract_address, storage_slot, note_type_id, encryption_pub_key, log ); - context.accumulate_encrypted_logs(log); + context.push_encrypted_log(log_hash); } pub fn emit_unencrypted_log(context: &mut PublicContext, log: T) { let contract_address = context.this_address(); let event_selector = 5; // TODO: compute actual event selector. - let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log); - // context.accumulate_unencrypted_logs(log); + let log_hash = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log); + context.push_unencrypted_log(log_hash); } // TODO: We might want to remove this since emitting unencrypted logs from private functions is violating privacy. @@ -34,6 +34,7 @@ pub fn emit_unencrypted_log(context: &mut PublicContext, log: T) { pub fn emit_unencrypted_log_from_private(context: &mut PrivateContext, log: T) { let contract_address = context.this_address(); let event_selector = 5; // TODO: compute actual event selector. - let _ = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log); + let log_hash = oracle::logs::emit_unencrypted_log(contract_address, event_selector, log); + context.push_unencrypted_log(log_hash); // context.accumulate_unencrypted_logs(log); } diff --git a/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr b/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr index f1de424f840..2bbf2337117 100644 --- a/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr +++ b/noir-projects/aztec-nr/aztec/src/oracle/arguments.nr @@ -1,11 +1,24 @@ +#[oracle(packArgumentsArray)] +fn pack_arguments_array_oracle(_args: [Field; N]) -> Field {} + #[oracle(packArguments)] -fn pack_arguments_oracle(_args: [Field; N]) -> Field {} +fn pack_arguments_oracle(_args: [Field]) -> Field {} + +/// - Pack arguments (array version) will notify the simulator that these arguments will be used later at +/// some point in the call. +/// - When the external call is made later, the simulator will know what the values unpack to. +/// - This oracle will not be required in public vm functions, as the vm will keep track of arguments +/// itself. +unconstrained pub fn pack_arguments_array(args: [Field; N]) -> Field { + pack_arguments_array_oracle(args) +} -/// - Pack arguments will notify the simulator that these arguments will be used later at +/// - Pack arguments (slice version) will notify the simulator that these arguments will be used later at /// some point in the call. /// - When the external call is made later, the simulator will know what the values unpack to. /// - This oracle will not be required in public vm functions, as the vm will keep track of arguments /// itself. -unconstrained pub fn pack_arguments(args: [Field; N]) -> Field { +unconstrained pub fn pack_arguments(args: [Field]) -> Field { pack_arguments_oracle(args) } + diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr index fa61113bc78..533639390d8 100644 --- a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable.nr @@ -1,4 +1,6 @@ mod shared_mutable; mod scheduled_value_change; +mod shared_mutable_private_getter; use shared_mutable::SharedMutable; +use shared_mutable_private_getter::SharedMutablePrivateGetter; diff --git a/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr new file mode 100644 index 00000000000..2f4f4339481 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/state_vars/shared_mutable/shared_mutable_private_getter.nr @@ -0,0 +1,70 @@ +use dep::protocol_types::{hash::pedersen_hash, traits::FromField, address::AztecAddress}; + +use crate::context::{PrivateContext, Context}; +use crate::history::public_storage::public_storage_historical_read; +use crate::public_storage; +use crate::state_vars::{storage::Storage, shared_mutable::scheduled_value_change::ScheduledValueChange}; + +struct SharedMutablePrivateGetter { + context: PrivateContext, + // The contract address of the contract we want to read from + other_contract_address: AztecAddress, + // The storage slot where the SharedMutable is stored on the other contract + storage_slot: Field, +} + +// We have this as a view-only interface to reading Shared Mutables in other contracts. +// Currently the Shared Mutable does not support this. We can adapt SharedMutable at a later date +impl SharedMutablePrivateGetter { + pub fn new( + context: PrivateContext, + other_contract_address: AztecAddress, + storage_slot: Field, + ) -> Self { + assert(storage_slot != 0, "Storage slot 0 not allowed. Storage slots must start from 1."); + assert(other_contract_address.to_field() != 0, "Other contract address cannot be 0"); + Self { context, other_contract_address, storage_slot } + } + + pub fn get_current_value_in_private(self) -> T where T: FromField { + let mut context = self.context; + + let (scheduled_value_change, historical_block_number) = self.historical_read_from_public_storage(context); + let block_horizon = scheduled_value_change.get_block_horizon(historical_block_number); + + // We prevent this transaction from being included in any block after the block horizon, ensuring that the + // historical public value matches the current one, since it can only change after the horizon. + context.set_tx_max_block_number(block_horizon); + scheduled_value_change.get_current_at(historical_block_number) + } + + fn historical_read_from_public_storage( + self, + context: PrivateContext + ) -> (ScheduledValueChange, u32) where T: FromField { + let derived_slot = self.get_derived_storage_slot(); + + // Ideally the following would be simply public_storage::read_historical, but we can't implement that yet. + let mut raw_fields = [0; 3]; + for i in 0..3 { + raw_fields[i] = public_storage_historical_read( + context, + derived_slot + i as Field, + self.other_contract_address + ); + } + + let scheduled_value: ScheduledValueChange = ScheduledValueChange::deserialize(raw_fields); + let historical_block_number = context.historical_header.global_variables.block_number as u32; + + (scheduled_value, historical_block_number) + } + + fn get_derived_storage_slot(self) -> Field { + // Since we're actually storing three values (a ScheduledValueChange struct), we hash the storage slot to get a + // unique location in which we can safely store as much data as we need. This could be removed if we informed + // the slot allocator of how much space we need so that proper padding could be added. + // See https://github.com/AztecProtocol/aztec-packages/issues/5492 + pedersen_hash([self.storage_slot, 0], 0) + } +} diff --git a/noir-projects/noir-contracts/Nargo.toml b/noir-projects/noir-contracts/Nargo.toml index 73e8bb9295e..b3d1c57c752 100644 --- a/noir-projects/noir-contracts/Nargo.toml +++ b/noir-projects/noir-contracts/Nargo.toml @@ -24,6 +24,7 @@ members = [ "contracts/escrow_contract", "contracts/gas_token_contract", "contracts/import_test_contract", + "contracts/key_registry_contract", "contracts/inclusion_proofs_contract", "contracts/lending_contract", "contracts/parent_contract", diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/app_subscription_contract/Nargo.toml index 34df286511b..cf460fd9497 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/Nargo.toml @@ -7,3 +7,5 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } authwit = { path = "../../../aztec-nr/authwit" } +gas_token = { path = "../gas_token_contract" } +token = { path = "../token_contract" } \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index 999f07771bd..eb316f30186 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -17,6 +17,9 @@ contract AppSubscription { use crate::subscription_note::{SubscriptionNote, SUBSCRIPTION_NOTE_LEN}; + use dep::gas_token::GasToken; + use dep::token::Token; + #[aztec(storage)] struct Storage { // The following is only needed in private but we use ShareImmutable here instead of PrivateImmutable because @@ -44,19 +47,11 @@ contract AppSubscription { note.remaining_txs -= 1; storage.subscriptions.at(user_address).replace(&mut note, true); - context.call_public_function( - storage.gas_token_address.read_private(), - FunctionSelector::from_signature("pay_fee(Field)"), - [42] - ); + GasToken::at(storage.gas_token_address.read_private()).pay_fee(42).enqueue(&mut context); context.capture_min_revertible_side_effect_counter(); - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("assert_not_expired(Field)"), - [note.expiry_block_number] - ); + AppSubscription::at(context.this_address()).assert_not_expired(note.expiry_block_number).enqueue(&mut context); payload.execute_calls(&mut context, storage.target_address.read_private()); } @@ -102,20 +97,15 @@ contract AppSubscription { ) { assert(tx_count as u64 <= SUBSCRIPTION_TXS as u64); - let _ = context.call_private_function( - storage.subscription_token_address.read_private(), - FunctionSelector::from_signature("transfer((Field),(Field),Field,Field)"), - [ - context.msg_sender().to_field(), storage.subscription_recipient_address.read_private().to_field(), storage.subscription_price.read_private(), nonce - ] - ); + Token::at(storage.subscription_token_address.read_private()).transfer( + context.msg_sender(), + storage.subscription_recipient_address.read_private(), + storage.subscription_price.read_private(), + nonce + ).call(&mut context); // Assert that the given expiry_block_number < current_block_number + SUBSCRIPTION_DURATION_IN_BLOCKS. - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("assert_block_number(Field)"), - [expiry_block_number] - ); + AppSubscription::at(context.this_address()).assert_block_number(expiry_block_number).enqueue(&mut context); let mut subscription_note = SubscriptionNote::new(subscriber_address, expiry_block_number, tx_count); if (!is_initialized(subscriber_address)) { diff --git a/noir-projects/noir-contracts/contracts/avm_acvm_interop_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_acvm_interop_test_contract/src/main.nr index c1af41666e9..bece62fc8dc 100644 --- a/noir-projects/noir-contracts/contracts/avm_acvm_interop_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_acvm_interop_test_contract/src/main.nr @@ -42,7 +42,7 @@ contract AvmAcvmInteropTest { context.call_public_function( context.this_address(), FunctionSelector::from_signature("constant_field_acvm()"), - [], + [].as_slice(), GasOpts::default() ).deserialize_into() } @@ -52,14 +52,19 @@ contract AvmAcvmInteropTest { context.call_public_function( context.this_address(), FunctionSelector::from_signature("constant_field_avm()"), - [], + [].as_slice(), GasOpts::default() ).deserialize_into() } #[aztec(public-vm)] fn avm_to_acvm_call(selector: FunctionSelector, args: Field) { - context.call_public_function(context.this_address(), selector, [args], GasOpts::default()).assert_empty(); + context.call_public_function( + context.this_address(), + selector, + [args].as_slice(), + GasOpts::default() + ).assert_empty(); } /************************************************************************ diff --git a/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr index 4c056f838de..e5d34183f42 100644 --- a/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_nested_calls_test_contract/src/main.nr @@ -42,7 +42,7 @@ contract AvmNestedCallsTest { GasOpts::default(), context.this_address(), selector, - [arg_a, arg_b] + [arg_a, arg_b].as_slice() ); let data_to_return: [Field; 1] = results.0; // this explicit size is necessary to ensure that ret_size is compile-time @@ -71,7 +71,7 @@ contract AvmNestedCallsTest { GasOpts::new(l1_gas, l2_gas, da_gas), context.this_address(), selector, - [arg_a, arg_b] + [arg_a, arg_b].as_slice() ); let data_to_return: [Field; 1] = results.0; // this explicit size is necessary to ensure that ret_size is compile-time @@ -85,15 +85,7 @@ contract AvmNestedCallsTest { // Use the `call_public_function` wrapper to initiate a nested call to the add function #[aztec(public-vm)] fn nested_call_to_add(arg_a: Field, arg_b: Field) -> pub Field { - let selector = FunctionSelector::from_signature("add_args_return(Field,Field)"); - - // Nested call using standard context interface function - context.call_public_function( - context.this_address(), - selector, - [arg_a, arg_b], - GasOpts::default() - ).deserialize_into() + AvmNestedCallsTest::at(context.this_address()).add_args_return(arg_a, arg_b).call(&mut context, GasOpts::default()) } // Directly call_static the external call opcode to initiate a nested call to the add function @@ -105,7 +97,7 @@ contract AvmNestedCallsTest { GasOpts::default(), context.this_address(), selector, - [arg_a, arg_b] + [arg_a, arg_b].as_slice() ); (result_data[0], success) @@ -117,7 +109,12 @@ contract AvmNestedCallsTest { let selector = FunctionSelector::from_signature("set_storage_single(Field)").to_field(); let calldata: [Field; 1] = [20]; - let (_data_to_return, success): ([Field; 0], u8) = context.static_call_public_function_raw(GasOpts::default(), context.this_address(), selector, calldata); + let (_data_to_return, success): ([Field; 0], u8) = context.static_call_public_function_raw( + GasOpts::default(), + context.this_address(), + selector, + calldata.as_slice() + ); success } @@ -125,40 +122,24 @@ contract AvmNestedCallsTest { // Indirectly call_static the external call opcode to initiate a nested call to the add function #[aztec(public-vm)] fn nested_static_call_to_add(arg_a: Field, arg_b: Field) -> pub Field { - let selector = FunctionSelector::from_signature("add_args_return(Field,Field)"); - - context.static_call_public_function( - context.this_address(), - selector, - [arg_a, arg_b], - GasOpts::default() - ).deserialize_into() + AvmNestedCallsTest::at(context.this_address()).add_args_return(arg_a, arg_b).static_call(&mut context, GasOpts::default()) } // Indirectly call_static `set_storage_single`. Should revert since it's accessing storage. #[aztec(public-vm)] fn nested_static_call_to_set_storage() { - let selector = FunctionSelector::from_signature("set_storage_single(Field)"); - let calldata: [Field; 1] = [20]; - - context.static_call_public_function(context.this_address(), selector, calldata, GasOpts::default()).assert_empty(); + AvmNestedCallsTest::at(context.this_address()).set_storage_single(20).static_call(&mut context, GasOpts::default()); } #[aztec(public-vm)] fn create_same_nullifier_in_nested_call(nestedAddress: AztecAddress, nullifier: Field) { context.push_new_nullifier(nullifier, 0); - - let selector = FunctionSelector::from_signature("new_nullifier(Field)"); - let calldata: [Field; 1] = [nullifier]; - let _ : FunctionReturns<0> = context.call_public_function(nestedAddress, selector, calldata, GasOpts::default()); + AvmNestedCallsTest::at(nestedAddress).new_nullifier(nullifier).call(&mut context, GasOpts::default()); } #[aztec(public-vm)] fn create_different_nullifier_in_nested_call(nestedAddress: AztecAddress, nullifier: Field) { context.push_new_nullifier(nullifier, 0); - - let selector = FunctionSelector::from_signature("new_nullifier(Field)"); - let calldata: [Field; 1] = [nullifier + 1]; - let _ : FunctionReturns<0> = context.call_public_function(nestedAddress, selector, calldata, GasOpts::default()); + AvmNestedCallsTest::at(nestedAddress).new_nullifier(nullifier + 1).call(&mut context, GasOpts::default()); } } diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 0102de54324..7eb12dd0e7c 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -265,10 +265,10 @@ contract AvmTest { #[aztec(public-vm)] fn emit_unencrypted_log() { - context.accumulate_unencrypted_logs(/*event_selector=*/ 5, /*message=*/ [10, 20, 30]); - context.accumulate_unencrypted_logs(/*event_selector=*/ 8, /*message=*/ "Hello, world!"); + context.emit_unencrypted_log(/*event_selector=*/ 5, /*message=*/ [10, 20, 30]); + context.emit_unencrypted_log(/*event_selector=*/ 8, /*message=*/ "Hello, world!"); let s: CompressedString<2,44> = CompressedString::from_string("A long time ago, in a galaxy far far away..."); - context.accumulate_unencrypted_logs(/*event_selector=*/ 10, /*message=*/ s); + context.emit_unencrypted_log(/*event_selector=*/ 10, /*message=*/ s); } #[aztec(public-vm)] diff --git a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr index 4e688ceb987..38511fc3a9f 100644 --- a/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/benchmarking_contract/src/main.nr @@ -44,12 +44,7 @@ contract Benchmarking { fn increment_balance(owner: AztecAddress, value: Field) { let current = storage.balances.at(owner).read(); storage.balances.at(owner).write(current + value); - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("broadcast((Field))"), - [owner.to_field()], - GasOpts::default() - ).assert_empty(); + Benchmarking::at(context.this_address()).broadcast(owner).call(&mut context); } // Emits a public log. diff --git a/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr b/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr index 1e54f0c2866..d4416eff7cd 100644 --- a/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/card_game_contract/src/main.nr @@ -39,13 +39,8 @@ contract CardGame { collection.remove_cards(cards, player); let mut game_deck = storage.game_decks.at(game as Field).at(player); let _added_to_game_deck = game_deck.add_cards(cards, player); - let selector = FunctionSelector::from_signature("on_game_joined(u32,(Field),u32)"); let strength = compute_deck_strength(cards); - context.call_public_function( - context.this_address(), - selector, - [game as Field, player.to_field(), strength] - ); + CardGame::at(context.this_address()).on_game_joined(game, player, strength as u32).enqueue(&mut context); } #[aztec(public)] @@ -75,13 +70,8 @@ contract CardGame { let mut game_deck = storage.game_decks.at(game as Field).at(player); game_deck.remove_cards([card], player); - let selector = FunctionSelector::from_signature("on_card_played(u32,(Field),Field)"); // docs:start:call_public_function - context.call_public_function( - context.this_address(), - selector, - [game as Field, player.to_field(), card.to_field()] - ); + CardGame::at(context.this_address()).on_card_played(game, player, card.to_field()).enqueue(&mut context); // docs:end:call_public_function } @@ -107,13 +97,7 @@ contract CardGame { let mut collection = storage.collections.at(player); let _inserted_cards = collection.add_cards(cards, player); - - let selector = FunctionSelector::from_signature("on_cards_claimed(u32,(Field),Field)"); - context.call_public_function( - context.this_address(), - selector, - [game as Field, player.to_field(), pedersen_hash(cards_fields, 0)] - ); + CardGame::at(context.this_address()).on_cards_claimed(game, player, pedersen_hash(cards_fields, 0)).enqueue(&mut context); } #[aztec(public)] diff --git a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr index 8304aaecb3b..15117e2dbfa 100644 --- a/noir-projects/noir-contracts/contracts/child_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/child_contract/src/main.nr @@ -94,14 +94,7 @@ contract Child { #[aztec(public)] fn set_value_twice_with_nested_first() { - let pub_set_value_selector = FunctionSelector::from_signature("pub_set_value(Field)"); - let _result: Field = context.call_public_function( - context.this_address(), - pub_set_value_selector, - [10], - GasOpts::default() - ).deserialize_into(); - + let _result = Child::at(context.this_address()).pub_set_value(10).call(&mut context); storage.current_value.write(20); emit_unencrypted_log(&mut context, 20); } @@ -110,13 +103,6 @@ contract Child { fn set_value_twice_with_nested_last() { storage.current_value.write(20); emit_unencrypted_log(&mut context, 20); - - let pub_set_value_selector = FunctionSelector::from_signature("pub_set_value(Field)"); - let _result: Field = context.call_public_function( - context.this_address(), - pub_set_value_selector, - [10], - GasOpts::default() - ).deserialize_into(); + let _result = Child::at(context.this_address()).pub_set_value(10).call(&mut context); } } diff --git a/noir-projects/noir-contracts/contracts/claim_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/claim_contract/Nargo.toml index 1db74bdf3ac..7d81995453f 100644 --- a/noir-projects/noir-contracts/contracts/claim_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/claim_contract/Nargo.toml @@ -7,3 +7,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } value_note = { path = "../../../aztec-nr/value-note" } +token = { path = "../token_contract" } diff --git a/noir-projects/noir-contracts/contracts/claim_contract/src/interfaces.nr b/noir-projects/noir-contracts/contracts/claim_contract/src/interfaces.nr deleted file mode 100644 index a7e14c8d9fc..00000000000 --- a/noir-projects/noir-contracts/contracts/claim_contract/src/interfaces.nr +++ /dev/null @@ -1,37 +0,0 @@ -use dep::aztec::{ - protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}, - context::PrivateContext -}; - -struct Token { - address: AztecAddress, -} - -impl Token { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - fn mint_public(self: Self, context: &mut PrivateContext, to: AztecAddress, amount: Field) { - let _ret = context.call_public_function( - self.address, - FunctionSelector::from_signature("mint_public((Field),Field)"), - [to.to_field(), amount] - ); - } - - pub fn transfer( - self: Self, - context: &mut PrivateContext, - from: AztecAddress, - to: AztecAddress, - amount: Field, - nonce: Field - ) { - let _ret = context.call_private_function( - self.address, - FunctionSelector::from_signature("transfer((Field),(Field),Field,Field)"), - [from.to_field(), to.to_field(), amount, nonce] - ); - } -} diff --git a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr index 6cac882ba6f..090ea87a0a0 100644 --- a/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/claim_contract/src/main.nr @@ -1,13 +1,11 @@ contract Claim { - mod interfaces; - use dep::aztec::{ history::note_inclusion::prove_note_inclusion, protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}, state_vars::SharedImmutable }; use dep::value_note::value_note::ValueNote; - use interfaces::Token; + use dep::token::Token; #[aztec(storage)] struct Storage { @@ -43,7 +41,6 @@ contract Claim { context.push_new_nullifier(proof_note.compute_nullifier(&mut context), 0); // 4) Finally we mint the reward token to the sender of the transaction - let reward_token = Token::at(storage.reward_token.read_private()); - reward_token.mint_public(&mut context, recipient, proof_note.value); + Token::at(storage.reward_token.read_private()).mint_public(recipient, proof_note.value).enqueue(&mut context); } } diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/crowdfunding_contract/Nargo.toml index 78810768a4d..aa72f2f65f4 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/Nargo.toml @@ -7,3 +7,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } value_note = { path = "../../../aztec-nr/value-note" } +token = { path = "../token_contract" } diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/interfaces.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/interfaces.nr deleted file mode 100644 index 746f8e0e24c..00000000000 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/interfaces.nr +++ /dev/null @@ -1,27 +0,0 @@ -use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::{AztecAddress, EthAddress}}; -use dep::aztec::{context::{PrivateContext, PublicContext}}; - -struct Token { - address: AztecAddress, -} - -impl Token { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn transfer( - self: Self, - context: &mut PrivateContext, - from: AztecAddress, - to: AztecAddress, - amount: Field, - nonce: Field - ) { - let _ret = context.call_private_function( - self.address, - FunctionSelector::from_signature("transfer((Field),(Field),Field,Field)"), - [from.to_field(), to.to_field(), amount, nonce] - ); - } -} diff --git a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr index 42a0883fabd..76d6335e6ff 100644 --- a/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/crowdfunding_contract/src/main.nr @@ -1,5 +1,4 @@ contract Crowdfunding { - mod interfaces; use dep::aztec::{ log::emit_unencrypted_log_from_private, @@ -7,7 +6,7 @@ contract Crowdfunding { state_vars::{PrivateSet, PublicImmutable, SharedImmutable} }; use dep::value_note::value_note::ValueNote; - use interfaces::Token; + use dep::token::Token; #[aztec(event)] struct WithdrawalProcessed { @@ -51,21 +50,15 @@ contract Crowdfunding { #[aztec(private)] fn donate(amount: u64) { // 1) Check that the deadline has not passed - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("_check_deadline()"), - [] - ); + Crowdfunding::at(context.this_address())._check_deadline().enqueue(&mut context); // 2) Transfer the donation tokens from donor to this contract - let donation_token = Token::at(storage.donation_token.read_private()); - donation_token.transfer( - &mut context, + Token::at(storage.donation_token.read_private()).transfer( context.msg_sender(), context.this_address(), amount as Field, 0 - ); + ).call(&mut context); // 3) Create a value note for the donor so that he can later on claim a rewards token in the Claim // contract by proving that the hash of this note exists in the note hash tree. @@ -81,14 +74,7 @@ contract Crowdfunding { assert(context.msg_sender() == operator_address, "Not an operator"); // 2) Transfer the donation tokens from this contract to the operator - let donation_token = Token::at(storage.donation_token.read_private()); - donation_token.transfer( - &mut context, - context.this_address(), - operator_address, - amount as Field, - 0 - ); + Token::at(storage.donation_token.read_private()).transfer(context.this_address(), operator_address, amount as Field, 0).call(&mut context); // 3) Emit an unencrypted event so that anyone can audit how much the operator has withdrawn let event = WithdrawalProcessed { amount, who: operator_address }; diff --git a/noir-projects/noir-contracts/contracts/delegator_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/delegator_contract/Nargo.toml index 8299f932ad2..1aad229b828 100644 --- a/noir-projects/noir-contracts/contracts/delegator_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/delegator_contract/Nargo.toml @@ -6,4 +6,5 @@ compiler_version = ">=0.25.0" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } -value_note = { path = "../../../aztec-nr/value-note" } \ No newline at end of file +value_note = { path = "../../../aztec-nr/value-note" } +delegated_on = { path = "../delegated_on_contract"} \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr index 5cb189e7410..939c2f1907f 100644 --- a/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/delegator_contract/src/main.nr @@ -5,6 +5,7 @@ contract Delegator { PublicMutable, PrivateSet, Deserialize }; use dep::value_note::value_note::ValueNote; + use dep::delegated_on::DelegatedOn; #[aztec(storage)] struct Storage { @@ -15,29 +16,21 @@ contract Delegator { #[aztec(private)] fn private_delegate_set_value( target_contract: AztecAddress, - target_selector: FunctionSelector, - args: [Field; 2] + value: Field, + owner: AztecAddress ) -> Field { // Call the target private function - context.delegate_call_private_function(target_contract, target_selector, args).unpack_into() + DelegatedOn::at(target_contract).private_set_value(value, owner).delegate_call(&mut context) } #[aztec(private)] - fn enqueued_delegate_set_value( - target_contract: AztecAddress, - target_selector: FunctionSelector, - args: [Field; 1] - ) { - context.delegate_call_public_function(target_contract, target_selector, args); + fn enqueued_delegate_set_value(target_contract: AztecAddress, value: Field) { + DelegatedOn::at(target_contract).public_set_value(value).delegate_enqueue(&mut context) } #[aztec(public)] - fn public_delegate_set_value( - target_contract: AztecAddress, - target_selector: FunctionSelector, - args: [Field; 1] - ) { - let _result: Field = context.delegate_call_public_function(target_contract, target_selector, args).deserialize_into(); + fn public_delegate_set_value(target_contract: AztecAddress, value: Field) -> Field { + DelegatedOn::at(target_contract).public_set_value(value).delegate_call(&mut context) } unconstrained fn view_private_value(amount: Field, owner: AztecAddress) -> pub Field { diff --git a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr index ae0d5e3d40a..4c4eb170e98 100644 --- a/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/docs_example_contract/src/main.nr @@ -115,10 +115,9 @@ contract DocsExample { // and returns the response. // Used to test that we can retrieve values through calls and // correctly return them in the simulation - context.call_private_function_no_args( - context.this_address(), - FunctionSelector::from_signature("get_shared_immutable_constrained_private()") - ).unpack_into() + let mut leader = DocsExample::at(context.this_address()).get_shared_immutable_constrained_private().call(&mut context); + leader.points += 1; + leader } #[aztec(public)] @@ -127,10 +126,9 @@ contract DocsExample { // and returns the response. // Used to test that we can retrieve values through calls and // correctly return them in the simulation - context.call_public_function_no_args( - context.this_address(), - FunctionSelector::from_signature("get_shared_immutable_constrained_public()") - ).deserialize_into() + let mut leader = DocsExample::at(context.this_address()).get_shared_immutable_constrained_public().call(&mut context); + leader.points += 1; + leader } #[aztec(public)] @@ -138,6 +136,12 @@ contract DocsExample { storage.shared_immutable.read_public() } + #[aztec(public)] + fn get_shared_immutable_constrained_public_multiple() -> pub [Leader; 5] { + let a = storage.shared_immutable.read_public(); + [a, a, a, a, a] + } + #[aztec(private)] fn get_shared_immutable_constrained_private() -> pub Leader { storage.shared_immutable.read_private() @@ -178,7 +182,7 @@ contract DocsExample { } #[aztec(private)] - fn insert_notes(amounts: [u8; 10]) { + fn insert_notes(amounts: [u8; 3]) { for i in 0..amounts.len() { let mut note = CardNote::new(amounts[i], 1, context.msg_sender()); storage.set.insert(&mut note, true); @@ -210,12 +214,7 @@ contract DocsExample { fn update_legendary_card(randomness: Field, points: u8) { let mut new_card = CardNote::new(points, randomness, context.msg_sender()); storage.legendary_card.replace(&mut new_card, true); - - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("update_leader((Field),u8)"), - [context.msg_sender().to_field(), points as Field] - ); + DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue(&mut context); } #[aztec(private)] @@ -234,11 +233,7 @@ contract DocsExample { storage.legendary_card.replace(&mut new_card, true); // docs:end:state_vars-PrivateMutableReplace - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("update_leader((Field),u8)"), - [context.msg_sender().to_field(), points as Field] - ); + DocsExample::at(context.this_address()).update_leader(context.msg_sender(), points).enqueue(&mut context); } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr index a9081073066..1b5af4b8280 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_token_contract/src/main.nr @@ -1,7 +1,7 @@ // docs:start:easy_private_token_contract contract EasyPrivateToken { use dep::aztec::prelude::{AztecAddress, NoteHeader, Map}; - use dep::value_note::{balance_utils, value_note::ValueNote}; + use dep::value_note::balance_utils; use dep::easy_private_state::EasyPrivateUint; #[aztec(storage)] diff --git a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr index 76cc88e1201..634acdb45bd 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr @@ -30,11 +30,7 @@ contract EasyPrivateVoting { let secret = context.request_nullifier_secret_key(context.msg_sender()); // get secret key of caller of function let nullifier = dep::std::hash::pedersen_hash([context.msg_sender().to_field(), secret.low, secret.high]); // compute nullifier with this secret key so others can't descrypt it context.push_new_nullifier(nullifier, 0); // push nullifier - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("add_to_tally_public(Field)"), - [candidate] - ); + EasyPrivateVoting::at(context.this_address()).add_to_tally_public(candidate).enqueue(&mut context); } // docs:end:cast_vote diff --git a/noir-projects/noir-contracts/contracts/escrow_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/escrow_contract/Nargo.toml index 9982ff8b67f..a0c107d21a4 100644 --- a/noir-projects/noir-contracts/contracts/escrow_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/escrow_contract/Nargo.toml @@ -7,3 +7,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } address_note = { path = "../../../aztec-nr/address-note" } +token = { path = "../token_contract" } \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr index 709c65b3ec5..c1ec425486b 100644 --- a/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/escrow_contract/src/main.nr @@ -6,6 +6,8 @@ contract Escrow { use dep::address_note::address_note::AddressNote; + use dep::token::Token; + #[aztec(storage)] struct Storage { owner: PrivateImmutable, @@ -28,11 +30,6 @@ contract Escrow { let note = storage.owner.get_note(); assert(note.address == sender); - let selector = FunctionSelector::from_signature("transfer((Field),(Field),Field,Field)"); - let _callStackItem = context.call_private_function( - token, - selector, - [this.to_field(), recipient.to_field(), amount, 0] - ); + Token::at(token).transfer(this, recipient, amount, 0).call(&mut context); } } diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/fpc_contract/Nargo.toml index 887ffaf17d0..96bd8bacba7 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/fpc_contract/Nargo.toml @@ -7,3 +7,5 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } authwit = { path = "../../../aztec-nr/authwit" } +token = { path = "../token_contract" } +gas_token = { path = "../gas_token_contract" } diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/interfaces.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/interfaces.nr deleted file mode 100644 index f2f94f9884a..00000000000 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/interfaces.nr +++ /dev/null @@ -1,60 +0,0 @@ -use dep::aztec::prelude::{AztecAddress, EthAddress, FunctionSelector, PrivateContext, Deserialize}; -use dep::aztec::context::{PublicContext, gas::GasOpts}; - -struct Token { - address: AztecAddress, -} - -impl Token { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn transfer_public( - self: Self, - context: &mut PublicContext, - from: AztecAddress, - to: AztecAddress, - amount: Field, - nonce: Field - ) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("transfer_public((Field),(Field),Field,Field)"), - [from.to_field(), to.to_field(), amount, nonce], - GasOpts::default() - ).assert_empty(); - } - - pub fn shield( - self: Self, - context: &mut PublicContext, - from: AztecAddress, - amount: Field, - secret_hash: Field, - nonce: Field - ) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("shield((Field),Field,Field,Field)"), - [from.to_field(), amount, secret_hash, nonce], - GasOpts::default() - ).assert_empty(); - } - - // Private - pub fn unshield( - self: Self, - context: &mut PrivateContext, - from: AztecAddress, - to: AztecAddress, - amount: Field, - nonce: Field - ) { - context.call_private_function( - self.address, - FunctionSelector::from_signature("unshield((Field),(Field),Field,Field)"), - [from.to_field(), to.to_field(), amount, nonce] - ); - } -} diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr index 118fcd71c07..f7636711d0e 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr @@ -1,11 +1,9 @@ -mod interfaces; - contract FPC { use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress, traits::is_empty}; use dep::aztec::state_vars::SharedImmutable; - use dep::aztec::prelude::Deserialize; + use dep::token::Token; + use dep::gas_token::GasToken; use dep::aztec::context::gas::GasOpts; - use crate::interfaces::Token; #[aztec(storage)] struct Storage { @@ -23,67 +21,34 @@ contract FPC { #[aztec(private)] fn fee_entrypoint_private(amount: Field, asset: AztecAddress, secret_hash: Field, nonce: Field) { assert(asset == storage.other_asset.read_private()); - - let _res = Token::at(asset).unshield( - &mut context, - context.msg_sender(), - context.this_address(), - amount, - nonce - ); - - let _void = context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("pay_fee_with_shielded_rebate(Field,(Field),Field)"), - [amount, asset.to_field(), secret_hash] - ); + Token::at(asset).unshield(context.msg_sender(), context.this_address(), amount, nonce).call(&mut context); + FPC::at(context.this_address()).pay_fee_with_shielded_rebate(amount, asset, secret_hash).enqueue(&mut context); } #[aztec(private)] fn fee_entrypoint_public(amount: Field, asset: AztecAddress, nonce: Field) { - let _void = context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("prepare_fee((Field),Field,(Field),Field)"), - [context.msg_sender().to_field(), amount, asset.to_field(), nonce] - ); - - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("pay_fee((Field),Field,(Field))"), - [context.msg_sender().to_field(), amount, asset.to_field()] - ); + FPC::at(context.this_address()).prepare_fee(context.msg_sender(), amount, asset, nonce).enqueue(&mut context); + FPC::at(context.this_address()).pay_fee(context.msg_sender(), amount, asset).enqueue(&mut context); } #[aztec(public)] #[aztec(internal)] fn prepare_fee(from: AztecAddress, amount: Field, asset: AztecAddress, nonce: Field) { - let _res = Token::at(asset).transfer_public(&mut context, from, context.this_address(), amount, nonce); + Token::at(asset).transfer_public(from, context.this_address(), amount, nonce).call(&mut context); } #[aztec(public)] #[aztec(internal)] fn pay_fee(refund_address: AztecAddress, amount: Field, asset: AztecAddress) { - let refund: Field = context.call_public_function( - storage.gas_token_address.read_public(), - FunctionSelector::from_signature("pay_fee(Field)"), - [amount], - GasOpts::default() - ).deserialize_into(); - + let refund = GasToken::at(storage.gas_token_address.read_public()).pay_fee(amount).call(&mut context); // Just do public refunds for the present - Token::at(asset).transfer_public(&mut context, context.this_address(), refund_address, refund, 0) + Token::at(asset).transfer_public(context.this_address(), refund_address, refund, 0).call(&mut context); } #[aztec(public)] #[aztec(internal)] fn pay_fee_with_shielded_rebate(amount: Field, asset: AztecAddress, secret_hash: Field) { - let refund: Field = context.call_public_function( - storage.gas_token_address.read_public(), - FunctionSelector::from_signature("pay_fee(Field)"), - [amount], - GasOpts::default() - ).deserialize_into(); - - Token::at(asset).shield(&mut context, context.this_address(), refund, secret_hash, 0); + let refund = GasToken::at(storage.gas_token_address.read_public()).pay_fee(amount).call(&mut context); + Token::at(asset).shield(context.this_address(), refund, secret_hash, 0).call(&mut context); } } diff --git a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr index ba8ecf6c608..ec1adf32116 100644 --- a/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/gas_token_contract/src/main.nr @@ -12,11 +12,11 @@ contract GasToken { } #[aztec(public)] - fn claim_public(to: AztecAddress, amount: Field, secret: Field) { + fn claim_public(to: AztecAddress, amount: Field, secret: Field, leaf_index: Field) { let content_hash = get_bridge_gas_msg_hash(to, amount); // Consume message and emit nullifier - context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address()); + context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address(), leaf_index); let new_balance = storage.balances.at(to).read() + U128::from_integer(amount); storage.balances.at(to).write(new_balance); diff --git a/noir-projects/noir-contracts/contracts/import_test_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/import_test_contract/Nargo.toml index f4ec2663e2b..fe205fd0f17 100644 --- a/noir-projects/noir-contracts/contracts/import_test_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/import_test_contract/Nargo.toml @@ -6,3 +6,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } +test = { path = "../test_contract"} diff --git a/noir-projects/noir-contracts/contracts/import_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/import_test_contract/src/main.nr index 0168119b822..9224c0c2a3e 100644 --- a/noir-projects/noir-contracts/contracts/import_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/import_test_contract/src/main.nr @@ -1,54 +1,44 @@ -mod test_contract_interface; - // Contract that uses the autogenerated interface of the Test contract for calling its functions. // Used for testing calling into other contracts via autogenerated interfaces. contract ImportTest { - use dep::aztec::prelude::{AztecAddress, Deserialize}; + use dep::aztec::prelude::AztecAddress; + + use dep::test::{Test, Test::DeepStruct, Test::DummyNote}; - use crate::test_contract_interface::{ - TestPrivateContextInterface, TestPublicContextInterface, AStructTestCodeGenStruct, - ADeepStructTestCodeGenStruct, ANoteADeepStructTestCodeGenStruct, - ManyNotesADeepStructTestCodeGenStruct - }; + use dep::test::Test::FieldNote; + use dep::test::Test::ValueNote; // Calls the test_code_gen on the Test contract at the target address // Used for testing calling a function with arguments of multiple types // See yarn-project/simulator/src/client/private_execution.ts // See yarn-project/end-to-end/src/e2e_nested_contract.test.ts #[aztec(private)] - fn main(target: AztecAddress) -> Field { - let test_contract_instance = TestPrivateContextInterface::at(target); - let returned_field: Field = test_contract_instance.test_code_gen( - &mut context, + fn main_contract(target: AztecAddress) -> Field { + Test::at(target).test_code_gen( 1, true, 1 as u32, [1, 2], - AStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, - ADeepStructTestCodeGenStruct { + DummyNote { amount: 1, secret_hash: 2 }, + DeepStruct { a_field: 1, a_bool: true, - a_note: ANoteADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, + a_note: DummyNote { amount: 1, secret_hash: 2 }, many_notes: [ - ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, - ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 }, - ManyNotesADeepStructTestCodeGenStruct { amount: 1, secret_hash: 2 } + DummyNote { amount: 1, secret_hash: 2 }, + DummyNote { amount: 1, secret_hash: 2 }, + DummyNote { amount: 1, secret_hash: 2 } ] } - ).unpack_into(); - - returned_field + ).call(&mut context) } // Calls the get_this_address on the Test contract at the target address // Used for testing calling a function with no arguments // See yarn-project/end-to-end/src/e2e_nested_contract.test.ts #[aztec(private)] - fn call_no_args(target: AztecAddress) -> Field { - let test_contract_instance = TestPrivateContextInterface::at(target); - let returned_field: Field = test_contract_instance.get_this_address(&mut context).unpack_into(); - - returned_field + fn call_no_args(target: AztecAddress) -> AztecAddress { + Test::at(target).get_this_address().call(&mut context) } // Calls the create_nullifier_public on the Test contract at the target address @@ -56,8 +46,7 @@ contract ImportTest { // See yarn-project/end-to-end/src/e2e_nested_contract.test.ts #[aztec(private)] fn call_open_fn(target: AztecAddress) { - let test_contract_instance = TestPrivateContextInterface::at(target); - test_contract_instance.create_nullifier_public(&mut context, 1, 2); + Test::at(target).create_nullifier_public(1, 2).enqueue(&mut context); } // Calls the create_nullifier_public on the Test contract at the target address @@ -65,8 +54,7 @@ contract ImportTest { // See yarn-project/end-to-end/src/e2e_nested_contract.test.ts #[aztec(public)] fn pub_call_open_fn(target: AztecAddress) { - let test_contract_instance = TestPublicContextInterface::at(target); - test_contract_instance.create_nullifier_public(&mut context, 1, 2).assert_empty(); + Test::at(target).create_nullifier_public(1, 2).call(&mut context); } } diff --git a/noir-projects/noir-contracts/contracts/import_test_contract/src/test_contract_interface.nr b/noir-projects/noir-contracts/contracts/import_test_contract/src/test_contract_interface.nr deleted file mode 120000 index 1113fbe816e..00000000000 --- a/noir-projects/noir-contracts/contracts/import_test_contract/src/test_contract_interface.nr +++ /dev/null @@ -1 +0,0 @@ -../../test_contract/src/interface.nr \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml new file mode 100644 index 00000000000..cae3a7ead7e --- /dev/null +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "key_registry_contract" +authors = [""] +compiler_version = ">=0.25.0" +type = "contract" + +[dependencies] +aztec = { path = "../../../aztec-nr/aztec" } +authwit = { path = "../../../aztec-nr/authwit" } diff --git a/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr new file mode 100644 index 00000000000..8f2810f3dbf --- /dev/null +++ b/noir-projects/noir-contracts/contracts/key_registry_contract/src/main.nr @@ -0,0 +1,118 @@ +contract KeyRegistry { + use dep::std::hash::poseidon2::Poseidon2::hash as poseidon2_hash; + use dep::authwit::auth::assert_current_call_valid_authwit_public; + + use dep::aztec::{ + context::gas::GasOpts, + state_vars::{ + SharedMutable, + Map + }, + protocol_types::{ + abis::function_selector::FunctionSelector, + contract_class_id::ContractClassId, + address::{ + AztecAddress, + EthAddress, + PublicKeysHash, + PartialAddress, + }, + constants::{ + GENERATOR_INDEX__CONTRACT_ADDRESS_V1, + GENERATOR_INDEX__PUBLIC_KEYS_HASH + }, + traits::{ + Serialize, + Deserialize, + } + }, + }; + + global KEY_ROTATION_DELAY = 5; + + #[aztec(storage)] + struct Storage { + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality + nullifier_public_key_registry: Map>, + // incoming_public_key_registry: Map>, + // outgoing_public_key_registry: Map>, + // tagging_public_key_registry: Map>, + } + + #[aztec(public)] + fn rotate_nullifier_public_key( + address: AztecAddress, + new_nullifier_public_key: Field, + ) { + assert( + new_nullifier_public_key != 0, + "New nullifier public key must be non-zero" + ); + + if (!address.eq(context.msg_sender())) { + assert_current_call_valid_authwit_public(&mut context, address); + } + + let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); + + nullifier_key_registry.schedule_value_change(new_nullifier_public_key); + } + + #[aztec(public)] + fn register( + address: AztecAddress, + partial_address: PartialAddress, + nullifier_public_key: Field, + incoming_public_key: Field, + outgoing_public_key: Field, + tagging_public_key: Field, + ) { + assert( + (nullifier_public_key != 0) & + (incoming_public_key != 0) & + (outgoing_public_key != 0) & + (tagging_public_key != 0), + "All public keys must be non-zero" + ); + + // TODO (ek): Do it below after refactoring all public_keys_hash_elemtns + // let public_keys_hash = PublicKeysHash::compute(nullifier_public_key, tagging_public_key, incoming_public_key, outgoing_public_key); + // let address = AztecAddress::compute(public_keys_hash, partial_address); + // We could also pass in original_public_keys_hash instead of computing it here, if all we need the original one is for being able to prove ownership of address + let public_keys_hash = poseidon2_hash([ + nullifier_public_key, + incoming_public_key, + outgoing_public_key, + tagging_public_key, + GENERATOR_INDEX__PUBLIC_KEYS_HASH, + ], + 5 + ); + + let computed_address = AztecAddress::from_field( + poseidon2_hash([ + partial_address.to_field(), + public_keys_hash.to_field(), + GENERATOR_INDEX__CONTRACT_ADDRESS_V1 as Field, + ], + 3 + ) + ); + + assert(computed_address.eq(address), "Computed address does not match supplied address"); + + let nullifier_key_registry = storage.nullifier_public_key_registry.at(address); + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality + // let incoming_key_registry = storage.incoming_public_key_registry.at(address); + // let outgoing_key_registry = storage.outgoing_public_key_registry.at(address); + // let tagging_key_registry = storage.taggin_public_key_registry.at(address); + + nullifier_key_registry.schedule_value_change(nullifier_public_key); + // We are not supporting rotating / changing keys other than the nullifier public in the registry at the moment, but will in the future. + // Uncomment lines below to enable that functionality // incoming_key_registry.schedule_value_change(new_incoming_public_key); + // outgoing_key_registry.schedule_value_change(new_outgoing_public_key); + // tagging_key_registry.schedule_value_change(new_tagging_public_key); + } +} diff --git a/noir-projects/noir-contracts/contracts/lending_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/lending_contract/Nargo.toml index e6a337360bc..f1e58a4ef1f 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/lending_contract/Nargo.toml @@ -6,3 +6,5 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } +token = { path = "../token_contract" } +price_feed = { path = "../price_feed_contract" } diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr index 5dc8cb7f300..7415ec54d92 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/asset.nr @@ -1,7 +1,7 @@ use dep::aztec::prelude::AztecAddress; use dep::aztec::protocol_types::traits::{Deserialize, Serialize}; -// Struct to be used to represent "totals". Generally, there should be one per asset. +// Struct to be used to represent "totals". Generally, there should be one per Asset. // It stores the global values that are shared among all users, such as an accumulator // and last time it was updated. // In practice, it should also point to an oracle and have more fields related to @@ -13,23 +13,23 @@ struct Asset { oracle: AztecAddress, } -global ASSET_SERIALIZED_LEN: Field = 4; +global SERIALIZED_LEN: Field = 4; -impl Serialize for Asset { - fn serialize(asset: Asset) -> [Field; ASSET_SERIALIZED_LEN] { +impl Serialize for Asset { + fn serialize(Asset: Asset) -> [Field; SERIALIZED_LEN] { [ - asset.interest_accumulator.to_integer(), - asset.last_updated_ts as Field, - asset.loan_to_value.to_integer(), - asset.oracle.to_field() + Asset.interest_accumulator.to_integer(), + Asset.last_updated_ts as Field, + Asset.loan_to_value.to_integer(), + Asset.oracle.to_field() ] } } -impl Deserialize for Asset { +impl Deserialize for Asset { // Right now we are wasting so many writes. If changing last_updated_ts // we will end up rewriting all of them, wasting writes. - fn deserialize(fields: [Field; ASSET_SERIALIZED_LEN]) -> Asset { + fn deserialize(fields: [Field; SERIALIZED_LEN]) -> Asset { let interest_accumulator = U128::from_integer(fields[0]); let last_updated_ts = fields[1] as u64; let loan_to_value = U128::from_integer(fields[2]); diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/interfaces.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/interfaces.nr deleted file mode 100644 index 5a2e31ec79f..00000000000 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/interfaces.nr +++ /dev/null @@ -1,117 +0,0 @@ -use dep::aztec::prelude::{FunctionSelector, AztecAddress, PrivateContext, Deserialize}; - -use dep::aztec::context::{PublicContext, gas::GasOpts}; - -use crate::asset::Asset; - -struct PriceFeed { - address: AztecAddress, -} - -impl PriceFeed { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn get_price(self: Self, context: &mut PublicContext) -> U128 { - let price_field: Field = context.call_public_function( - self.address, - FunctionSelector::from_signature("get_price(Field)"), - [0], - GasOpts::default() - ).deserialize_into(); - - U128::from_integer(price_field) - } -} - -struct Token { - address: AztecAddress, -} - -impl Token { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn transfer_public( - self: Self, - context: &mut PublicContext, - from: AztecAddress, - to: AztecAddress, - amount: Field, - nonce: Field - ) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("transfer_public((Field),(Field),Field,Field)"), - [from.to_field(), to.to_field(), amount, nonce], - GasOpts::default() - ).assert_empty(); - } - - pub fn mint_public(self: Self, context: &mut PublicContext, to: AztecAddress, amount: Field) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("mint_public((Field),Field)"), - [to.to_field(), amount], - GasOpts::default() - ).assert_empty(); - } - - pub fn burn_public( - self: Self, - context: &mut PublicContext, - from: AztecAddress, - amount: Field, - nonce: Field - ) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("burn_public((Field),Field,Field)"), - [from.to_field(), amount, nonce], - GasOpts::default() - ).assert_empty(); - } - - // Private - pub fn unshield( - self: Self, - context: &mut PrivateContext, - from: AztecAddress, - to: AztecAddress, - amount: Field, - nonce: Field - ) { - context.call_private_function( - self.address, - FunctionSelector::from_signature("unshield((Field),(Field),Field,Field)"), - [from.to_field(), to.to_field(), amount, nonce] - ); - } - - pub fn burn(self: Self, context: &mut PrivateContext, from: AztecAddress, amount: Field, nonce: Field) { - context.call_private_function( - self.address, - FunctionSelector::from_signature("burn((Field),Field,Field)"), - [from.to_field(), amount, nonce] - ); - } -} - -struct Lending { - address: AztecAddress, -} - -impl Lending { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn update_accumulator(self: Self, context: &mut PublicContext) -> Asset { - context.call_public_function_no_args( - self.address, - FunctionSelector::from_signature("update_accumulator()") - ).deserialize_into() - } -} diff --git a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr index 37727015e25..c2c05f58a09 100644 --- a/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/lending_contract/src/main.nr @@ -1,7 +1,6 @@ mod asset; mod interest_math; mod helpers; -mod interfaces; // Single asset CDP contract. // Shoving re-entries up the ass. @@ -17,7 +16,8 @@ contract Lending { use crate::asset::Asset; use crate::interest_math::compute_multiplier; use crate::helpers::{covered_by_collateral, DebtReturn, debt_updates, debt_value, compute_identifier}; - use crate::interfaces::{Token, Lending, PriceFeed}; + use dep::token::Token; + use dep::price_feed::PriceFeed; // Storage structure, containing all storage, and specifying what slots they use. #[aztec(storage)] @@ -49,7 +49,7 @@ contract Lending { stable_coin: AztecAddress ) { let asset_loc = storage.assets.at(0); - let asset = asset_loc.read(); + let asset: Asset = asset_loc.read(); let loan_to_value = U128::from_integer(loan_to_value); @@ -71,7 +71,7 @@ contract Lending { #[aztec(public)] fn update_accumulator() -> Asset { let asset_loc = storage.assets.at(0); - let mut asset = asset_loc.read(); + let mut asset: Asset = asset_loc.read(); let timestamp = context.timestamp(); let dt = timestamp - asset.last_updated_ts; @@ -103,38 +103,28 @@ contract Lending { collateral_asset: AztecAddress ) { let on_behalf_of = compute_identifier(secret, on_behalf_of, context.msg_sender().to_field()); - let _res = Token::at(collateral_asset).unshield(&mut context, from, context.this_address(), amount, nonce); - // _deposit(on_behalf_of, amount, collateral_asset) - let selector = FunctionSelector::from_signature("_deposit((Field),Field,(Field))"); - context.call_public_function( - context.this_address(), - selector, - [on_behalf_of, amount, collateral_asset.to_field()] - ); + let _res = Token::at(collateral_asset).unshield(from, context.this_address(), amount, nonce).call(&mut context); + Lending::at(context.this_address())._deposit( + AztecAddress::from_field(on_behalf_of), + amount, + collateral_asset + ).enqueue(&mut context); } #[aztec(public)] fn deposit_public(amount: Field, nonce: Field, on_behalf_of: Field, collateral_asset: AztecAddress) { - Token::at(collateral_asset).transfer_public( - &mut context, - context.msg_sender(), - context.this_address(), + let _ = Token::at(collateral_asset).transfer_public(context.msg_sender(), context.this_address(), amount, nonce).call(&mut context); + let _ = Lending::at(context.this_address())._deposit( + AztecAddress::from_field(on_behalf_of), amount, - nonce - ); - let selector = FunctionSelector::from_signature("_deposit((Field),Field,(Field))"); - context.call_public_function( - context.this_address(), - selector, - [on_behalf_of, amount, collateral_asset.to_field()], - GasOpts::default() - ).assert_empty(); + collateral_asset + ).call(&mut context); } #[aztec(public)] #[aztec(internal)] fn _deposit(owner: AztecAddress, amount: Field, collateral_asset: AztecAddress) { - let _asset = Lending::at(context.this_address()).update_accumulator(&mut context); + let _asset = Lending::at(context.this_address()).update_accumulator().call(&mut context); let coll_asset = storage.collateral_asset.read(); assert(coll_asset.eq(collateral_asset)); @@ -147,30 +137,19 @@ contract Lending { #[aztec(private)] fn withdraw_private(secret: Field, to: AztecAddress, amount: Field) { let on_behalf_of = compute_identifier(secret, 0, context.msg_sender().to_field()); - let selector = FunctionSelector::from_signature("_withdraw((Field),(Field),Field)"); - context.call_public_function( - context.this_address(), - selector, - [on_behalf_of, to.to_field(), amount] - ); + Lending::at(context.this_address())._withdraw(AztecAddress::from_field(on_behalf_of), to, amount).enqueue(&mut context); } #[aztec(public)] fn withdraw_public(to: AztecAddress, amount: Field) { - let selector = FunctionSelector::from_signature("_withdraw((Field),(Field),Field)"); - context.call_public_function( - context.this_address(), - selector, - [context.msg_sender().to_field(), to.to_field(), amount], - GasOpts::default() - ).assert_empty(); + let _ = Lending::at(context.this_address())._withdraw(context.msg_sender(), to, amount).call(&mut context); } #[aztec(public)] #[aztec(internal)] fn _withdraw(owner: AztecAddress, recipient: AztecAddress, amount: Field) { - let asset = Lending::at(context.this_address()).update_accumulator(&mut context); - let price = PriceFeed::at(asset.oracle).get_price(&mut context); + let asset = Lending::at(context.this_address()).update_accumulator().call(&mut context); + let price = PriceFeed::at(asset.oracle).get_price(0).call(&mut context).price; let coll_loc = storage.collateral.at(owner); let collateral: Field = coll_loc.read(); @@ -200,36 +179,25 @@ contract Lending { // @todo @LHerskind Support both shielding and transfers (for now just transfer) let collateral_asset = storage.collateral_asset.read(); - Token::at(collateral_asset).transfer_public(&mut context, context.this_address(), recipient, amount, 0); + let _ = Token::at(collateral_asset).transfer_public(context.this_address(), recipient, amount, 0).call(&mut context); } #[aztec(private)] fn borrow_private(secret: Field, to: AztecAddress, amount: Field) { let on_behalf_of = compute_identifier(secret, 0, context.msg_sender().to_field()); - let selector = FunctionSelector::from_signature("_borrow((Field),(Field),Field)"); - context.call_public_function( - context.this_address(), - selector, - [on_behalf_of, to.to_field(), amount] - ); + let _ = Lending::at(context.this_address())._borrow(AztecAddress::from_field(on_behalf_of), to, amount).enqueue(&mut context); } #[aztec(public)] fn borrow_public(to: AztecAddress, amount: Field) { - let selector = FunctionSelector::from_signature("_borrow((Field),(Field),Field)"); - context.call_public_function( - context.this_address(), - selector, - [context.msg_sender().to_field(), to.to_field(), amount], - GasOpts::default() - ).assert_empty(); + let _ = Lending::at(context.this_address())._borrow(context.msg_sender(), to, amount).call(&mut context); } #[aztec(public)] #[aztec(internal)] fn _borrow(owner: AztecAddress, to: AztecAddress, amount: Field) { - let asset = Lending::at(context.this_address()).update_accumulator(&mut context); - let price = PriceFeed::at(asset.oracle).get_price(&mut context); + let asset = Lending::at(context.this_address()).update_accumulator().call(&mut context); + let price = PriceFeed::at(asset.oracle).get_price(0).call(&mut context).price; // Fetch collateral and static_debt, compute health of current position let collateral = U128::from_integer(storage.collateral.at(owner).read()); @@ -255,7 +223,7 @@ contract Lending { // @todo @LHerskind Need to support both private and public minting. let stable_coin = storage.stable_coin.read(); - Token::at(stable_coin).mint_public(&mut context, to, amount); + let _ = Token::at(stable_coin).mint_public(to, amount).call(&mut context); } #[aztec(private)] @@ -268,31 +236,20 @@ contract Lending { stable_coin: AztecAddress ) { let on_behalf_of = compute_identifier(secret, on_behalf_of, context.msg_sender().to_field()); - let _res = Token::at(stable_coin).burn(&mut context, from, amount, nonce); - let selector = FunctionSelector::from_signature("_repay((Field),Field,(Field))"); - context.call_public_function( - context.this_address(), - selector, - [on_behalf_of, amount, stable_coin.to_field()] - ); + let _ = Token::at(stable_coin).burn(from, amount, nonce).call(&mut context); + let _ = Lending::at(context.this_address())._repay(AztecAddress::from_field(on_behalf_of), amount, stable_coin).enqueue(&mut context); } #[aztec(public)] fn repay_public(amount: Field, nonce: Field, owner: AztecAddress, stable_coin: AztecAddress) { - Token::at(stable_coin).burn_public(&mut context, context.msg_sender(), amount, nonce); - let selector = FunctionSelector::from_signature("_repay((Field),Field,(Field))"); - context.call_public_function( - context.this_address(), - selector, - [owner.to_field(), amount, stable_coin.to_field()], - GasOpts::default() - ).assert_empty(); + let _ = Token::at(stable_coin).burn_public(context.msg_sender(), amount, nonce).call(&mut context); + let _ = Lending::at(context.this_address())._repay(owner, amount, stable_coin).call(&mut context); } #[aztec(public)] #[aztec(internal)] fn _repay(owner: AztecAddress, amount: Field, stable_coin: AztecAddress) { - let asset = Lending::at(context.this_address()).update_accumulator(&mut context); + let asset = Lending::at(context.this_address()).update_accumulator().call(&mut context); // To ensure that private is using the correct token. assert(stable_coin.eq(storage.stable_coin.read())); @@ -315,7 +272,7 @@ contract Lending { unconstrained fn get_position(owner: AztecAddress) -> pub Position { let collateral = storage.collateral.at(owner).read(); let static_debt = storage.static_debt.at(owner).read(); - let asset = storage.assets.at(0).read(); + let asset: Asset = storage.assets.at(0).read(); let debt = debt_value( U128::from_integer(static_debt), U128::from_integer(asset.interest_accumulator) diff --git a/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr b/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr index 5dffc5e6493..fb066de5ad6 100644 --- a/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/parent_contract/src/main.nr @@ -1,8 +1,8 @@ + // A contract used along with `Child` contract to test nested calls. contract Parent { use dep::aztec::prelude::{AztecAddress, FunctionSelector, Deserialize}; use dep::aztec::context::gas::GasOpts; - // Private function to call another private function in the target_contract using the provided selector #[aztec(private)] fn entry_point(target_contract: AztecAddress, target_selector: FunctionSelector) -> Field { @@ -20,7 +20,7 @@ contract Parent { context.call_public_function( target_contract, target_selector, - [init_value], + [init_value].as_slice(), GasOpts::default() ).deserialize_into() } @@ -35,13 +35,13 @@ contract Parent { let return_value: Field = context.call_public_function( target_contract, target_selector, - [init_value], + [init_value].as_slice(), GasOpts::default() ).deserialize_into(); context.call_public_function( target_contract, target_selector, - [return_value], + [return_value].as_slice(), GasOpts::default() ).deserialize_into() } @@ -189,7 +189,12 @@ contract Parent { target_selector: FunctionSelector, args: [Field; 1] ) -> Field { - context.static_call_public_function(target_contract, target_selector, args, GasOpts::default()).deserialize_into() + context.static_call_public_function( + target_contract, + target_selector, + args.as_slice(), + GasOpts::default() + ).deserialize_into() } // Public function to set a static context and verify correct propagation for nested public calls @@ -205,7 +210,7 @@ contract Parent { context.static_call_public_function( this_address, pub_entry_point_selector, - [target_contract.to_field(), target_selector.to_field(), args[0]], + [target_contract.to_field(), target_selector.to_field(), args[0]].as_slice(), GasOpts::default() ).deserialize_into() } diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/slow_tree_contract/Nargo.toml index 54270ccd97e..2edcc357b5a 100644 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/slow_tree_contract/Nargo.toml @@ -6,5 +6,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } -value_note = { path = "../../../aztec-nr/value-note" } slow_updates_tree = { path = "../../../aztec-nr/slow-updates-tree" } diff --git a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr index 2fa7b935a4b..f71c2ff62c5 100644 --- a/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/slow_tree_contract/src/main.nr @@ -12,7 +12,6 @@ contract SlowTree { Map, PublicMutable, PrivateSet }; - use dep::value_note::{balance_utils, utils::{increment, decrement}, value_note::ValueNote}; use dep::aztec::{context::{PublicContext, Context}, protocol_types::type_serialization::FIELD_SERIALIZED_LEN}; use dep::slow_updates_tree::{SlowMap, Leaf, SlowUpdateProof, compute_merkle_root, deserialize_slow_update_proof}; diff --git a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr index 3c7ac5c3af0..db8efde4a25 100644 --- a/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/stateful_test_contract/src/main.nr @@ -17,8 +17,7 @@ contract StatefulTest { #[aztec(private)] #[aztec(initializer)] fn constructor(owner: AztecAddress, value: Field) { - let selector = FunctionSelector::from_signature("create_note_no_init_check((Field),Field)"); - context.call_private_function(context.this_address(), selector, [owner.to_field(), value]).assert_empty(); + StatefulTest::at(context.this_address()).create_note_no_init_check(owner, value).call(&mut context); } #[aztec(private)] @@ -31,13 +30,7 @@ contract StatefulTest { #[aztec(public)] #[aztec(initializer)] fn public_constructor(owner: AztecAddress, value: Field) { - let selector = FunctionSelector::from_signature("increment_public_value_no_init_check((Field),Field)"); - context.call_public_function( - context.this_address(), - selector, - [owner.to_field(), value], - GasOpts::default() - ).assert_empty(); + StatefulTest::at(context.this_address()).increment_public_value_no_init_check(owner, value).call(&mut context); } #[aztec(private)] diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/interface.nr b/noir-projects/noir-contracts/contracts/test_contract/src/interface.nr deleted file mode 100644 index 71133236902..00000000000 --- a/noir-projects/noir-contracts/contracts/test_contract/src/interface.nr +++ /dev/null @@ -1,675 +0,0 @@ -/* Autogenerated file, do not edit! */ - -use dep::std; -use dep::aztec::context::{ PrivateContext, PublicContext, PackedReturns, FunctionReturns, gas::GasOpts }; -use dep::aztec::protocol_types::{ - address::AztecAddress, - abis::function_selector::FunctionSelector, -}; - -struct AddressGetPublicKeyStruct { - inner: Field, -} - -struct TargetDeployContractStruct { - inner: Field, -} - -struct SenderConsumeMessageFromArbitrarySenderPublicStruct { - inner: Field, -} - -struct ToConsumeMintPublicMessageStruct { - inner: Field, -} - -struct RecipientCreateL2ToL1MessageArbitraryRecipientPrivateStruct { - inner: Field, -} - -struct SenderConsumeMessageFromArbitrarySenderPrivateStruct { - inner: Field, -} - -struct CoinbaseAssertPublicGlobalVarsStruct { - inner: Field, -} - -struct FeeRecipientAssertPublicGlobalVarsStruct { - inner: Field, -} - -struct OwnerCallCreateNoteStruct { - inner: Field, -} - -struct AStructTestCodeGenStruct { - amount: Field, - secret_hash: Field, -} - -struct ADeepStructTestCodeGenStruct { - a_field: Field, - a_bool: bool, - a_note: ANoteADeepStructTestCodeGenStruct, - many_notes: [ManyNotesADeepStructTestCodeGenStruct;3], -} - -struct ANoteADeepStructTestCodeGenStruct { - amount: Field, - secret_hash: Field, -} - -struct ManyNotesADeepStructTestCodeGenStruct { - amount: Field, - secret_hash: Field, -} - -struct RecipientCreateL2ToL1MessageArbitraryRecipientPublicStruct { - inner: Field, -} - -struct AztecAddressGetPortalContractAddressStruct { - inner: Field, -} - - -// Interface for calling Test functions from a private context -struct TestPrivateContextInterface { - address: AztecAddress, -} - -impl TestPrivateContextInterface { - pub fn at(address: AztecAddress) -> Self { - Self { - address, - } - } - - pub fn get_public_key( - self, - context: &mut PrivateContext, - address: AddressGetPublicKeyStruct - ) -> PackedReturns{ - let mut serialized_args = [0; 1]; - serialized_args[0] = address.inner; - - context.call_private_function(self.address, FunctionSelector::from_field(0x501e4f48), serialized_args) - } - - - pub fn assert_header_public( - self, - context: &mut PrivateContext, - header_hash: Field - ) { - let mut serialized_args = [0; 1]; - serialized_args[0] = header_hash; - - context.call_public_function(self.address, FunctionSelector::from_field(0x86e38c61), serialized_args) - } - - - pub fn deploy_contract( - self, - context: &mut PrivateContext, - target: TargetDeployContractStruct - ) -> PackedReturns{ - let mut serialized_args = [0; 1]; - serialized_args[0] = target.inner; - - context.call_private_function(self.address, FunctionSelector::from_field(0x5acec588), serialized_args) - } - - - pub fn get_this_address( - self, - context: &mut PrivateContext - ) -> PackedReturns{ - let mut serialized_args = [0; 0]; - - context.call_private_function(self.address, FunctionSelector::from_field(0x95a7b2ae), serialized_args) - } - - - pub fn emit_msg_sender( - self, - context: &mut PrivateContext - ) -> PackedReturns{ - let mut serialized_args = [0; 0]; - - context.call_private_function(self.address, FunctionSelector::from_field(0x11fb5d45), serialized_args) - } - - - pub fn consume_message_from_arbitrary_sender_public( - self, - context: &mut PrivateContext, - content: Field, - secret: Field, - sender: SenderConsumeMessageFromArbitrarySenderPublicStruct - ) { - let mut serialized_args = [0; 3]; - serialized_args[0] = content; - serialized_args[1] = secret; - serialized_args[2] = sender.inner; - - context.call_public_function(self.address, FunctionSelector::from_field(0x42ca6d60), serialized_args) - } - - - pub fn emit_unencrypted( - self, - context: &mut PrivateContext, - value: Field - ) { - let mut serialized_args = [0; 1]; - serialized_args[0] = value; - - context.call_public_function(self.address, FunctionSelector::from_field(0x817a64cb), serialized_args) - } - - - pub fn consume_mint_public_message( - self, - context: &mut PrivateContext, - to: ToConsumeMintPublicMessageStruct, - amount: Field, - secret: Field - ) { - let mut serialized_args = [0; 3]; - serialized_args[0] = to.inner; - serialized_args[1] = amount; - serialized_args[2] = secret; - - context.call_public_function(self.address, FunctionSelector::from_field(0xa0f84219), serialized_args) - } - - - pub fn create_nullifier_public( - self, - context: &mut PrivateContext, - amount: Field, - secret_hash: Field - ) { - let mut serialized_args = [0; 2]; - serialized_args[0] = amount; - serialized_args[1] = secret_hash; - - context.call_public_function(self.address, FunctionSelector::from_field(0xdf02db8d), serialized_args) - } - - - pub fn call_get_notes_many( - self, - context: &mut PrivateContext, - storage_slot: Field, - active_or_nullified: bool - ) -> PackedReturns{ - let mut serialized_args = [0; 2]; - serialized_args[0] = storage_slot; - serialized_args[1] = active_or_nullified as Field; - - context.call_private_function(self.address, FunctionSelector::from_field(0xcfcadbce), serialized_args) - } - - - pub fn create_l2_to_l1_message_arbitrary_recipient_private( - self, - context: &mut PrivateContext, - content: Field, - recipient: RecipientCreateL2ToL1MessageArbitraryRecipientPrivateStruct - ) -> PackedReturns{ - let mut serialized_args = [0; 2]; - serialized_args[0] = content; - serialized_args[1] = recipient.inner; - - context.call_private_function(self.address, FunctionSelector::from_field(0xaccc5d5d), serialized_args) - } - - - pub fn consume_message_from_arbitrary_sender_private( - self, - context: &mut PrivateContext, - content: Field, - secret: Field, - sender: SenderConsumeMessageFromArbitrarySenderPrivateStruct - ) -> PackedReturns{ - let mut serialized_args = [0; 3]; - serialized_args[0] = content; - serialized_args[1] = secret; - serialized_args[2] = sender.inner; - - context.call_private_function(self.address, FunctionSelector::from_field(0x2847cb26), serialized_args) - } - - - pub fn create_l2_to_l1_message_public( - self, - context: &mut PrivateContext, - amount: Field, - secret_hash: Field - ) { - let mut serialized_args = [0; 2]; - serialized_args[0] = amount; - serialized_args[1] = secret_hash; - - context.call_public_function(self.address, FunctionSelector::from_field(0x9749ca06), serialized_args) - } - - - pub fn is_time_equal( - self, - context: &mut PrivateContext, - time: u64 - ) { - let mut serialized_args = [0; 1]; - serialized_args[0] = time as Field; - - context.call_public_function(self.address, FunctionSelector::from_field(0xb5bb17fa), serialized_args) - } - - - pub fn assert_private_global_vars( - self, - context: &mut PrivateContext, - chain_id: Field, - version: Field - ) -> PackedReturns{ - let mut serialized_args = [0; 2]; - serialized_args[0] = chain_id; - serialized_args[1] = version; - - context.call_private_function(self.address, FunctionSelector::from_field(0x7a8e9b66), serialized_args) - } - - - pub fn assert_public_global_vars( - self, - context: &mut PrivateContext, - chain_id: Field, - version: Field, - block_number: Field, - timestamp: u64, - coinbase: CoinbaseAssertPublicGlobalVarsStruct, - fee_recipient: FeeRecipientAssertPublicGlobalVarsStruct, - fee_per_da_gas: Field, - fee_per_l1_gas: Field, - fee_per_l2_gas: Field - ) { - let mut serialized_args = [0; 9]; - serialized_args[0] = chain_id; - serialized_args[1] = version; - serialized_args[2] = block_number; - serialized_args[3] = timestamp as Field; - serialized_args[4] = coinbase.inner; - serialized_args[5] = fee_recipient.inner; - serialized_args[6] = fee_per_da_gas; - serialized_args[7] = fee_per_l1_gas; - serialized_args[8] = fee_per_l2_gas; - - context.call_public_function(self.address, FunctionSelector::from_field(0x33b3a245), serialized_args) - } - - - pub fn consume_note_from_secret( - self, - context: &mut PrivateContext, - secret: Field - ) -> PackedReturns{ - let mut serialized_args = [0; 1]; - serialized_args[0] = secret; - - context.call_private_function(self.address, FunctionSelector::from_field(0x754932c8), serialized_args) - } - - - pub fn call_destroy_note( - self, - context: &mut PrivateContext, - storage_slot: Field - ) -> PackedReturns{ - let mut serialized_args = [0; 1]; - serialized_args[0] = storage_slot; - - context.call_private_function(self.address, FunctionSelector::from_field(0xf52a62f7), serialized_args) - } - - - pub fn call_create_note( - self, - context: &mut PrivateContext, - value: Field, - owner: OwnerCallCreateNoteStruct, - storage_slot: Field - ) -> PackedReturns{ - let mut serialized_args = [0; 3]; - serialized_args[0] = value; - serialized_args[1] = owner.inner; - serialized_args[2] = storage_slot; - - context.call_private_function(self.address, FunctionSelector::from_field(0x946991ff), serialized_args) - } - - - pub fn get_this_portal_address( - self, - context: &mut PrivateContext - ) -> PackedReturns{ - let mut serialized_args = [0; 0]; - - context.call_private_function(self.address, FunctionSelector::from_field(0xc71384f5), serialized_args) - } - - - pub fn call_get_notes( - self, - context: &mut PrivateContext, - storage_slot: Field, - active_or_nullified: bool - ) -> PackedReturns{ - let mut serialized_args = [0; 2]; - serialized_args[0] = storage_slot; - serialized_args[1] = active_or_nullified as Field; - - context.call_private_function(self.address, FunctionSelector::from_field(0x11eeb3ea), serialized_args) - } - - - pub fn test_code_gen( - self, - context: &mut PrivateContext, - a_field: Field, - a_bool: bool, - a_number: u32, - an_array: [Field;2], - a_struct: AStructTestCodeGenStruct, - a_deep_struct: ADeepStructTestCodeGenStruct - ) -> PackedReturns{ - let mut serialized_args = [0; 17]; - serialized_args[0] = a_field; - serialized_args[1] = a_bool as Field; - serialized_args[2] = a_number as Field; - serialized_args[3] = an_array[0]; - serialized_args[4] = an_array[1]; - serialized_args[5] = a_struct.amount; - serialized_args[6] = a_struct.secret_hash; - serialized_args[7] = a_deep_struct.a_field; - serialized_args[8] = a_deep_struct.a_bool as Field; - serialized_args[9] = a_deep_struct.a_note.amount; - serialized_args[10] = a_deep_struct.a_note.secret_hash; - serialized_args[11] = a_deep_struct.many_notes[0].amount; - serialized_args[12] = a_deep_struct.many_notes[0].secret_hash; - serialized_args[13] = a_deep_struct.many_notes[1].amount; - serialized_args[14] = a_deep_struct.many_notes[1].secret_hash; - serialized_args[15] = a_deep_struct.many_notes[2].amount; - serialized_args[16] = a_deep_struct.many_notes[2].secret_hash; - - context.call_private_function(self.address, FunctionSelector::from_field(0x0f054f9b), serialized_args) - } - - - pub fn set_constant( - self, - context: &mut PrivateContext, - value: Field - ) -> PackedReturns{ - let mut serialized_args = [0; 1]; - serialized_args[0] = value; - - context.call_private_function(self.address, FunctionSelector::from_field(0x1b3b9e18), serialized_args) - } - - - pub fn consume_mint_private_message( - self, - context: &mut PrivateContext, - secret_hash_for_redeeming_minted_notes: Field, - amount: Field, - secret_for_L1_to_L2_message_consumption: Field - ) -> PackedReturns{ - let mut serialized_args = [0; 3]; - serialized_args[0] = secret_hash_for_redeeming_minted_notes; - serialized_args[1] = amount; - serialized_args[2] = secret_for_L1_to_L2_message_consumption; - - context.call_private_function(self.address, FunctionSelector::from_field(0xa0fdbaa9), serialized_args) - } - - - pub fn create_l2_to_l1_message_arbitrary_recipient_public( - self, - context: &mut PrivateContext, - content: Field, - recipient: RecipientCreateL2ToL1MessageArbitraryRecipientPublicStruct - ) { - let mut serialized_args = [0; 2]; - serialized_args[0] = content; - serialized_args[1] = recipient.inner; - - context.call_public_function(self.address, FunctionSelector::from_field(0x2fb25188), serialized_args) - } - - - pub fn emit_nullifier( - self, - context: &mut PrivateContext, - nullifier: Field - ) -> PackedReturns{ - let mut serialized_args = [0; 1]; - serialized_args[0] = nullifier; - - context.call_private_function(self.address, FunctionSelector::from_field(0x82a8b183), serialized_args) - } - - - pub fn emit_array_as_unencrypted_log( - self, - context: &mut PrivateContext, - fields: [Field;5] - ) -> PackedReturns{ - let mut serialized_args = [0; 5]; - serialized_args[0] = fields[0]; - serialized_args[1] = fields[1]; - serialized_args[2] = fields[2]; - serialized_args[3] = fields[3]; - serialized_args[4] = fields[4]; - - context.call_private_function(self.address, FunctionSelector::from_field(0xe25cbdd3), serialized_args) - } - - - pub fn get_portal_contract_address( - self, - context: &mut PrivateContext, - aztec_address: AztecAddressGetPortalContractAddressStruct - ) -> PackedReturns{ - let mut serialized_args = [0; 1]; - serialized_args[0] = aztec_address.inner; - - context.call_private_function(self.address, FunctionSelector::from_field(0x30e5344b), serialized_args) - } - - - pub fn request_max_block_number( - self, - context: &mut PrivateContext, - max_block_number: u32, - enqueue_public_call: bool - ) -> PackedReturns{ - let mut serialized_args = [0; 2]; - serialized_args[0] = max_block_number as Field; - serialized_args[1] = enqueue_public_call as Field; - - context.call_private_function(self.address, FunctionSelector::from_field(0x6db24b2e), serialized_args) - } - - - pub fn assert_header_private( - self, - context: &mut PrivateContext, - header_hash: Field - ) -> PackedReturns{ - let mut serialized_args = [0; 1]; - serialized_args[0] = header_hash; - - context.call_private_function(self.address, FunctionSelector::from_field(0x4e45eb9e), serialized_args) - } - -} - - - - -// Interface for calling Test functions from a public context -struct TestPublicContextInterface { - address: AztecAddress, -} - -impl TestPublicContextInterface { - pub fn at(address: AztecAddress) -> Self { - Self { - address, - } - } - - pub fn assert_header_public( - self, - context: &mut PublicContext, - header_hash: Field - ) -> FunctionReturns { - let mut serialized_args = [0; 1]; - serialized_args[0] = header_hash; - - context.call_public_function(self.address, FunctionSelector::from_field(0x86e38c61), serialized_args, GasOpts::default()) - } - - - pub fn consume_message_from_arbitrary_sender_public( - self, - context: &mut PublicContext, - content: Field, - secret: Field, - sender: SenderConsumeMessageFromArbitrarySenderPublicStruct - ) -> FunctionReturns { - let mut serialized_args = [0; 3]; - serialized_args[0] = content; - serialized_args[1] = secret; - serialized_args[2] = sender.inner; - - context.call_public_function(self.address, FunctionSelector::from_field(0x42ca6d60), serialized_args, GasOpts::default()) - } - - - pub fn emit_unencrypted( - self, - context: &mut PublicContext, - value: Field - ) -> FunctionReturns { - let mut serialized_args = [0; 1]; - serialized_args[0] = value; - - context.call_public_function(self.address, FunctionSelector::from_field(0x817a64cb), serialized_args, GasOpts::default()) - } - - - pub fn consume_mint_public_message( - self, - context: &mut PublicContext, - to: ToConsumeMintPublicMessageStruct, - amount: Field, - secret: Field - ) -> FunctionReturns { - let mut serialized_args = [0; 3]; - serialized_args[0] = to.inner; - serialized_args[1] = amount; - serialized_args[2] = secret; - - context.call_public_function(self.address, FunctionSelector::from_field(0xa0f84219), serialized_args, GasOpts::default()) - } - - - pub fn create_nullifier_public( - self, - context: &mut PublicContext, - amount: Field, - secret_hash: Field - ) -> FunctionReturns { - let mut serialized_args = [0; 2]; - serialized_args[0] = amount; - serialized_args[1] = secret_hash; - - context.call_public_function(self.address, FunctionSelector::from_field(0xdf02db8d), serialized_args, GasOpts::default()) - } - - - pub fn create_l2_to_l1_message_public( - self, - context: &mut PublicContext, - amount: Field, - secret_hash: Field - ) -> FunctionReturns { - let mut serialized_args = [0; 2]; - serialized_args[0] = amount; - serialized_args[1] = secret_hash; - - context.call_public_function(self.address, FunctionSelector::from_field(0x9749ca06), serialized_args, GasOpts::default()) - } - - - pub fn is_time_equal( - self, - context: &mut PublicContext, - time: u64 - ) -> FunctionReturns { - let mut serialized_args = [0; 1]; - serialized_args[0] = time as Field; - - context.call_public_function(self.address, FunctionSelector::from_field(0xb5bb17fa), serialized_args, GasOpts::default()) - } - - - pub fn assert_public_global_vars( - self, - context: &mut PublicContext, - chain_id: Field, - version: Field, - block_number: Field, - timestamp: u64, - coinbase: CoinbaseAssertPublicGlobalVarsStruct, - fee_recipient: FeeRecipientAssertPublicGlobalVarsStruct, - fee_per_da_gas: Field, - fee_per_l1_gas: Field, - fee_per_l2_gas: Field - ) -> FunctionReturns { - let mut serialized_args = [0; 9]; - serialized_args[0] = chain_id; - serialized_args[1] = version; - serialized_args[2] = block_number; - serialized_args[3] = timestamp as Field; - serialized_args[4] = coinbase.inner; - serialized_args[5] = fee_recipient.inner; - serialized_args[6] = fee_per_da_gas; - serialized_args[7] = fee_per_l1_gas; - serialized_args[8] = fee_per_l2_gas; - - context.call_public_function(self.address, FunctionSelector::from_field(0x33b3a245), serialized_args, GasOpts::default()) - } - - - pub fn create_l2_to_l1_message_arbitrary_recipient_public( - self, - context: &mut PublicContext, - content: Field, - recipient: RecipientCreateL2ToL1MessageArbitraryRecipientPublicStruct - ) -> FunctionReturns { - let mut serialized_args = [0; 2]; - serialized_args[0] = content; - serialized_args[1] = recipient.inner; - - context.call_public_function(self.address, FunctionSelector::from_field(0x2fb25188), serialized_args, GasOpts::default()) - } - -} - - diff --git a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr index 663cafa4860..92e8ad6490c 100644 --- a/noir-projects/noir-contracts/contracts/test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/test_contract/src/main.nr @@ -7,8 +7,11 @@ contract Test { use dep::aztec::protocol_types::{ abis::private_circuit_public_inputs::PrivateCircuitPublicInputs, - constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTES_PER_PAGE} + constants::{MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NOTES_PER_PAGE}, traits::Serialize }; + + use dep::aztec::state_vars::shared_mutable::SharedMutablePrivateGetter; + // docs:start:unencrypted_import use dep::aztec::prelude::emit_unencrypted_log; // docs:end:unencrypted_import @@ -72,11 +75,7 @@ contract Test { context.set_tx_max_block_number(max_block_number); if enqueue_public_call { - let _ = context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("dummy_public_call()"), - [] - ); + Test::at(context.this_address()).dummy_public_call().enqueue(&mut context) } } @@ -179,18 +178,15 @@ contract Test { destroy_note(&mut context, note); } - // Test codegen for Aztec.nr interfaces - // See yarn-project/simulator/src/client/private_execution.test.ts 'nested calls through autogenerated interface' - // Note; this function is deliberately NOT annotated with #[aztec(private)] due to its use in tests + #[aztec(private)] fn test_code_gen( - inputs: PrivateContextInputs, a_field: Field, a_bool: bool, a_number: u32, an_array: [Field; 2], a_struct: DummyNote, a_deep_struct: DeepStruct - ) -> distinct pub PrivateCircuitPublicInputs { + ) -> Field { let mut args = ArgsHasher::new(); args.add(a_field); args.add(a_bool as Field); @@ -206,12 +202,7 @@ contract Test { args.add(note.amount); args.add(note.secret_hash); } - let args_hash = args.hash(); - let mut context = PrivateContext::new(inputs, args_hash); - let mut returns = ArgsHasher::new(); - returns.add(args_hash); - context.set_return_hash(returns); - context.finish() + args.hash() } // Purely exists for testing @@ -280,10 +271,20 @@ contract Test { } #[aztec(public)] - fn consume_mint_public_message(to: AztecAddress, amount: Field, secret: Field) { + fn consume_mint_public_message( + to: AztecAddress, + amount: Field, + secret: Field, + message_leaf_index: Field + ) { let content_hash = get_mint_public_content_hash(to, amount); // Consume message and emit nullifier - context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address()); + context.consume_l1_to_l2_message( + content_hash, + secret, + context.this_portal_address(), + message_leaf_index + ); } #[aztec(private)] @@ -305,10 +306,11 @@ contract Test { fn consume_message_from_arbitrary_sender_public( content: Field, secret: Field, - sender: EthAddress + sender: EthAddress, + message_leaf_index: Field ) { // Consume message and emit nullifier - context.consume_l1_to_l2_message(content, secret, sender); + context.consume_l1_to_l2_message(content, secret, sender, message_leaf_index); } #[aztec(private)] @@ -388,6 +390,42 @@ contract Test { constant.value } + #[aztec(private)] + fn test_shared_mutable_private_getter_for_registry_contract( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field, + address_to_get_in_registry: AztecAddress, + ) { + // We have to derive this slot to get the location of the shared mutable inside the Map + let derived_slot = dep::aztec::hash::pedersen_hash([storage_slot_of_shared_mutable, address_to_get_in_registry.to_field()], 0); + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let registry_private_getter: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, derived_slot); + let nullifier_public_key = registry_private_getter.get_current_value_in_private(); + + emit_unencrypted_log_from_private(&mut context, nullifier_public_key); + } + + #[aztec(private)] + fn test_shared_mutable_private_getter( + contract_address_to_read: AztecAddress, + storage_slot_of_shared_mutable: Field, + ) { + // It's a bit wonky because we need to know the delay for get_current_value_in_private to work correctly + let test: SharedMutablePrivateGetter = SharedMutablePrivateGetter::new(context, contract_address_to_read, storage_slot_of_shared_mutable); + let authorized = test.get_current_value_in_private(); + + emit_unencrypted_log_from_private(&mut context, authorized); + } + + #[aztec(public)] + fn delay() { + // We use this as a util function to "mine a block" + dep::aztec::log::emit_unencrypted_log( + &mut context, + "dummy" + ); + } + // Purely exists for testing unconstrained fn get_random(kinda_seed: Field) -> pub Field { kinda_seed * unsafe_rand() @@ -408,10 +446,36 @@ contract Test { } } + impl Serialize<2> for DummyNote { + fn serialize(self) -> [Field; 2] { + [self.amount, self.secret_hash] + } + } + struct DeepStruct { a_field: Field, a_bool: bool, a_note: DummyNote, many_notes: [DummyNote; 3], } + + // Serializing using "canonical" form. + // 1. Everything that fits in a field, *becomes* a Field + // 2. Strings become arrays of bytes (no strings here) + // 4. Arrays become arrays of Fields following rules 2 and 3 (no arrays here) + // 5. Structs become arrays of Fields, with every item defined in the same order as they are in Noir code, following rules 2, 3, 4 and 5 (recursive) + impl Serialize<10> for DeepStruct { + fn serialize(self) -> [Field; 10] { + let mut result = [0; 10]; + result[0] = self.a_field; + result[1] = self.a_bool as Field; + result[2] = self.a_note.amount; + result[3] = self.a_note.secret_hash; + for i in 0..3 { + result[4 + i * 2] = self.many_notes[i].amount; + result[5 + i * 2] = self.many_notes[i].secret_hash; + } + result + } + } } diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml index 493c9159332..54bc420b804 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/Nargo.toml @@ -8,3 +8,4 @@ type = "contract" aztec = { path = "../../../aztec-nr/aztec" } field_note = { path = "../../../aztec-nr/field-note" } authwit = { path = "../../../aztec-nr/authwit" } +slow_tree = { path = "../slow_tree_contract" } \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/interfaces.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/interfaces.nr deleted file mode 100644 index 601d9ba65f0..00000000000 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/interfaces.nr +++ /dev/null @@ -1,45 +0,0 @@ -use dep::aztec::protocol_types::{abis::function_selector::FunctionSelector, address::AztecAddress}; -use dep::aztec::prelude::Deserialize; -use dep::aztec::context::{PrivateContext, PublicContext, Context, gas::GasOpts}; - -struct SlowMap { - address: AztecAddress, -} - -impl SlowMap { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn initialize(self: Self, context: &mut PublicContext) { - context.call_public_function_no_args( - self.address, - FunctionSelector::from_signature("initialize()") - ).assert_empty(); - } - - pub fn read_at_pub(self: Self, context: &mut PublicContext, index: Field) -> Field { - context.call_public_function( - self.address, - FunctionSelector::from_signature("read_at_pub(Field)"), - [index], - GasOpts::default() - ).deserialize_into() - } - - pub fn read_at(self: Self, context: &mut PrivateContext, index: Field) -> Field { - context.call_private_function( - self.address, - FunctionSelector::from_signature("read_at(Field)"), - [index] - ).unpack_into() - } - - pub fn update_at_private(self: Self, context: &mut PrivateContext, index: Field, new_value: Field) { - let _ = context.call_private_function( - self.address, - FunctionSelector::from_signature("update_at_private(Field,Field)"), - [index, new_value] - ); - } -} diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index cfad6717cc9..ddb115c721e 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -1,6 +1,4 @@ mod types; -mod interfaces; - // Minimal token implementation that supports `AuthWit` accounts and the slow update tree. // The auth message follows a similar pattern to the cross-chain message and includes a designated caller. // The designated caller is ALWAYS used here, and not based on a flag as cross-chain. @@ -27,7 +25,7 @@ contract TokenBlacklist { use crate::types::{transparent_note::TransparentNote, token_note::TokenNote, balances_map::BalancesMap, roles::UserFlags}; // docs:start:interface - use crate::interfaces::SlowMap; + use dep::slow_tree::SlowTree; // docs:end:interface #[aztec(storage)] @@ -51,25 +49,20 @@ contract TokenBlacklist { storage.slow_update.initialize(slow_updates_contract); // docs:end:write_slow_update_public // docs:start:slowmap_initialize - SlowMap::at(slow_updates_contract).initialize(&mut context); + SlowTree::at(slow_updates_contract).initialize().call(&mut context); // docs:end:slowmap_initialize // We cannot do the following atm // let roles = UserFlags { is_admin: true, is_minter: false, is_blacklisted: false }.get_value().to_field(); - // SlowMap::at(slow_updates_contract).update_at_private(&mut context, admin.to_field(), roles); + // SlowTree::at(slow_updates_contract).update_at_private(&mut context, admin.to_field(), roles); } #[aztec(private)] fn init_slow_tree(user: AztecAddress) { let roles = UserFlags { is_admin: true, is_minter: false, is_blacklisted: false }.get_value().to_field(); // docs:start:get_and_update_private - let slow = SlowMap::at(storage.slow_update.read_private()); - slow.update_at_private(&mut context, user.to_field(), roles); + SlowTree::at(storage.slow_update.read_private()).update_at_private(user.to_field(), roles).call(&mut context); // docs:end:get_and_update_private - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("_init_slow_tree((Field))"), - [context.msg_sender().to_field()] - ); + TokenBlacklist::at(context.this_address())._init_slow_tree(context.msg_sender()).enqueue(&mut context); } #[aztec(public)] @@ -81,25 +74,27 @@ contract TokenBlacklist { #[aztec(private)] fn update_roles(user: AztecAddress, roles: Field) { // docs:start:slowmap_at - let slow = SlowMap::at(storage.slow_update.read_private()); + let slow = SlowTree::at(storage.slow_update.read_private()); // docs:end:slowmap_at - let caller_roles = UserFlags::new(U128::from_integer(slow.read_at(&mut context, context.msg_sender().to_field()))); + let role = slow.read_at(context.msg_sender().to_field()).call(&mut context); + + let caller_roles = UserFlags::new(U128::from_integer(role)); assert(caller_roles.is_admin, "caller is not admin"); - slow.update_at_private(&mut context, user.to_field(), roles); + slow.update_at_private(user.to_field(), roles).call(&mut context); } #[aztec(public)] fn mint_public(to: AztecAddress, amount: Field) { // docs:start:get_public - let slow = SlowMap::at(storage.slow_update.read_public()); + let slow = SlowTree::at(storage.slow_update.read_public()); // docs:end:get_public // docs:start:read_at_pub - let to_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(&mut context, to.to_field()))); + let to_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(to.to_field()).call(&mut context))); // docs:end:read_at_pub assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); - let caller_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(&mut context, context.msg_sender().to_field()))); + let caller_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(context.msg_sender().to_field()).call(&mut context))); assert(caller_roles.is_minter, "caller is not minter"); let amount = U128::from_integer(amount); @@ -112,8 +107,8 @@ contract TokenBlacklist { #[aztec(public)] fn mint_private(amount: Field, secret_hash: Field) { - let slow = SlowMap::at(storage.slow_update.read_public()); - let caller_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(&mut context, context.msg_sender().to_field()))); + let slow = SlowTree::at(storage.slow_update.read_public()); + let caller_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(context.msg_sender().to_field()).call(&mut context))); assert(caller_roles.is_minter, "caller is not minter"); let pending_shields = storage.pending_shields; @@ -126,8 +121,8 @@ contract TokenBlacklist { #[aztec(public)] fn shield(from: AztecAddress, amount: Field, secret_hash: Field, nonce: Field) { - let slow = SlowMap::at(storage.slow_update.read_public()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(&mut context, from.to_field()))); + let slow = SlowTree::at(storage.slow_update.read_public()); + let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(from.to_field()).call(&mut context))); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); if (!from.eq(context.msg_sender())) { @@ -149,10 +144,10 @@ contract TokenBlacklist { #[aztec(public)] fn transfer_public(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowMap::at(storage.slow_update.read_public()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(&mut context, from.to_field()))); + let slow = SlowTree::at(storage.slow_update.read_public()); + let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(from.to_field()).call(&mut context))); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); - let to_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(&mut context, to.to_field()))); + let to_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(to.to_field()).call(&mut context))); assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); if (!from.eq(context.msg_sender())) { @@ -171,8 +166,8 @@ contract TokenBlacklist { #[aztec(public)] fn burn_public(from: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowMap::at(storage.slow_update.read_public()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(&mut context, from.to_field()))); + let slow = SlowTree::at(storage.slow_update.read_public()); + let from_roles = UserFlags::new(U128::from_integer(slow.read_at_pub(from.to_field()).call(&mut context))); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); if (!from.eq(context.msg_sender())) { @@ -191,9 +186,9 @@ contract TokenBlacklist { #[aztec(private)] fn redeem_shield(to: AztecAddress, amount: Field, secret: Field) { - let slow = SlowMap::at(storage.slow_update.read_private()); + let slow = SlowTree::at(storage.slow_update.read_private()); // docs:start:slowmap_read_at - let to_roles = UserFlags::new(U128::from_integer(slow.read_at(&mut context, to.to_field()))); + let to_roles = UserFlags::new(U128::from_integer(slow.read_at(to.to_field()).call(&mut context))); // docs:end:slowmap_read_at assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); @@ -218,10 +213,10 @@ contract TokenBlacklist { #[aztec(private)] fn unshield(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowMap::at(storage.slow_update.read_private()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at(&mut context, from.to_field()))); + let slow = SlowTree::at(storage.slow_update.read_private()); + let from_roles = UserFlags::new(U128::from_integer(slow.read_at(from.to_field()).call(&mut context))); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); - let to_roles = UserFlags::new(U128::from_integer(slow.read_at(&mut context, to.to_field()))); + let to_roles = UserFlags::new(U128::from_integer(slow.read_at(to.to_field()).call(&mut context))); assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); if (!from.eq(context.msg_sender())) { @@ -239,10 +234,10 @@ contract TokenBlacklist { // docs:start:transfer_private #[aztec(private)] fn transfer(from: AztecAddress, to: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowMap::at(storage.slow_update.read_private()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at(&mut context, from.to_field()))); + let slow = SlowTree::at(storage.slow_update.read_private()); + let from_roles = UserFlags::new(U128::from_integer(slow.read_at(from.to_field()).call(&mut context))); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); - let to_roles = UserFlags::new(U128::from_integer(slow.read_at(&mut context, to.to_field()))); + let to_roles = UserFlags::new(U128::from_integer(slow.read_at(to.to_field()).call(&mut context))); assert(!to_roles.is_blacklisted, "Blacklisted: Recipient"); // docs:end:transfer_private @@ -259,8 +254,8 @@ contract TokenBlacklist { #[aztec(private)] fn burn(from: AztecAddress, amount: Field, nonce: Field) { - let slow = SlowMap::at(storage.slow_update.read_private()); - let from_roles = UserFlags::new(U128::from_integer(slow.read_at(&mut context, from.to_field()))); + let slow = SlowTree::at(storage.slow_update.read_private()); + let from_roles = UserFlags::new(U128::from_integer(slow.read_at(from.to_field()).call(&mut context))); assert(!from_roles.is_blacklisted, "Blacklisted: Sender"); if (!from.eq(context.msg_sender())) { diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/token_bridge_contract/Nargo.toml index da41973739d..75c729d9c50 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/Nargo.toml @@ -7,3 +7,4 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } token_portal_content_hash_lib = { path = "../token_portal_content_hash_lib" } +token = { path = "../token_contract" } diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr index 673e4b8aa7f..32f9653915b 100644 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr @@ -1,5 +1,4 @@ // docs:start:token_bridge_imports -mod token_interface; // Minimal implementation of the token bridge that can move funds between L1 <> L2. // The bridge has a corresponding Portal contract on L1 that it is attached to @@ -13,7 +12,7 @@ contract TokenBridge { use dep::token_portal_content_hash_lib::{get_mint_public_content_hash, get_mint_private_content_hash, get_withdraw_content_hash}; - use crate::token_interface::Token; + use dep::token::Token; // docs:end:token_bridge_imports // docs:start:token_bridge_storage_and_constructor @@ -35,14 +34,19 @@ contract TokenBridge { // docs:start:claim_public // Consumes a L1->L2 message and calls the token contract to mint the appropriate amount publicly #[aztec(public)] - fn claim_public(to: AztecAddress, amount: Field, secret: Field) { + fn claim_public(to: AztecAddress, amount: Field, secret: Field, message_leaf_index: Field) { let content_hash = get_mint_public_content_hash(to, amount); // Consume message and emit nullifier - context.consume_l1_to_l2_message(content_hash, secret, context.this_portal_address()); + context.consume_l1_to_l2_message( + content_hash, + secret, + context.this_portal_address(), + message_leaf_index + ); // Mint tokens - Token::at(storage.token.read()).mint_public(&mut context, to, amount); + Token::at(storage.token.read()).mint_public(to, amount).call(&mut context); } // docs:end:claim_public @@ -61,7 +65,7 @@ contract TokenBridge { context.message_portal(context.this_portal_address(), content); // Burn tokens - Token::at(storage.token.read()).burn_public(&mut context, context.msg_sender(), amount, nonce); + Token::at(storage.token.read()).burn_public(context.msg_sender(), amount, nonce).call(&mut context); } // docs:end:exit_to_l1_public // docs:start:claim_private @@ -118,7 +122,7 @@ contract TokenBridge { // docs:end:call_assert_token_is_same // Burn tokens - Token::at(token).burn(&mut context, context.msg_sender(), amount, nonce); + Token::at(token).burn(context.msg_sender(), amount, nonce).call(&mut context); } /// docs:end:exit_to_l1_private @@ -151,7 +155,7 @@ contract TokenBridge { #[aztec(public)] #[aztec(internal)] fn _call_mint_on_token(amount: Field, secret_hash: Field) { - Token::at(storage.token.read()).mint_private(&mut context, amount, secret_hash); + Token::at(storage.token.read()).mint_private(amount, secret_hash).call(&mut context); } // docs:end:call_mint_on_token diff --git a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/token_interface.nr b/noir-projects/noir-contracts/contracts/token_bridge_contract/src/token_interface.nr deleted file mode 100644 index 8cebb78da04..00000000000 --- a/noir-projects/noir-contracts/contracts/token_bridge_contract/src/token_interface.nr +++ /dev/null @@ -1,59 +0,0 @@ -// docs:start:token_bridge_token_interface -use dep::aztec::prelude::{FunctionSelector, AztecAddress, EthAddress, PrivateContext}; -use dep::aztec::context::{PublicContext, Context, gas::GasOpts}; - -struct Token { - address: AztecAddress, -} - -impl Token { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn mint_public(self: Self, context: &mut PublicContext, to: AztecAddress, amount: Field) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("mint_public((Field),Field)"), - [to.to_field(), amount], - GasOpts::default() - ).assert_empty(); - } - - // docs:start:public_burn_interface - pub fn burn_public( - self: Self, - context: &mut PublicContext, - from: AztecAddress, - amount: Field, - nonce: Field - ) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("burn_public((Field),Field,Field)"), - [from.to_field(), amount, nonce], - GasOpts::default() - ).assert_empty(); - } - // docs:end:public_burn_interface - - pub fn mint_private(self: Self, context: &mut PublicContext, amount: Field, secret_hash: Field) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("mint_private(Field,Field)"), - [amount, secret_hash], - GasOpts::default() - ).assert_empty(); - } - - // docs:start:private_burn_interface - pub fn burn(self: Self, context: &mut PrivateContext, from: AztecAddress, amount: Field, nonce: Field) { - let _return_values = context.call_private_function( - self.address, - FunctionSelector::from_signature("burn((Field),Field,Field)"), - [from.to_field(), amount, nonce] - ); - } - // docs:end:private_burn_interface -} -// docs:end:token_bridge_token_interface diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index 7924299b27c..7978fe76412 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -168,12 +168,7 @@ contract Token { #[aztec(private)] fn privately_mint_private_note(amount: Field) { storage.balances.add(context.msg_sender(), U128::from_integer(amount)); - let selector = FunctionSelector::from_signature("assert_minter_and_mint((Field),Field)"); - let _void = context.call_public_function( - context.this_address(), - selector, - [context.msg_sender().to_field(), amount] - ); + Token::at(context.this_address()).assert_minter_and_mint(context.msg_sender(), amount).enqueue(&mut context); } #[aztec(public)] @@ -277,8 +272,7 @@ contract Token { storage.balances.sub(from, U128::from_integer(amount)); - let selector = FunctionSelector::from_signature("_increase_public_balance((Field),Field)"); - let _void = context.call_public_function(context.this_address(), selector, [to.to_field(), amount]); + Token::at(context.this_address())._increase_public_balance(to, amount).enqueue(&mut context); } // docs:end:unshield @@ -312,8 +306,7 @@ contract Token { storage.balances.sub(from, U128::from_integer(amount)); - let selector = FunctionSelector::from_signature("_reduce_total_supply(Field)"); - let _void = context.call_public_function(context.this_address(), selector, [amount]); + Token::at(context.this_address())._reduce_total_supply(amount).enqueue(&mut context); } // docs:end:burn diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/Nargo.toml b/noir-projects/noir-contracts/contracts/uniswap_contract/Nargo.toml index cabd23e359e..dbc2b0cf06d 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/Nargo.toml +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/Nargo.toml @@ -7,3 +7,5 @@ type = "contract" [dependencies] aztec = { path = "../../../aztec-nr/aztec" } authwit = { path = "../../../aztec-nr/authwit" } +token = { path = "../token_contract" } +token_bridge = { path = "../token_bridge_contract" } \ No newline at end of file diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/interfaces.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/interfaces.nr deleted file mode 100644 index cd68492fabb..00000000000 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/interfaces.nr +++ /dev/null @@ -1,80 +0,0 @@ -// docs:start:interfaces -use dep::aztec::prelude::{FunctionSelector, AztecAddress, EthAddress, PrivateContext, Deserialize}; -use dep::aztec::context::{PublicContext, gas::GasOpts}; - -struct Token { - address: AztecAddress, -} - -impl Token { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn transfer_public( - self: Self, - context: &mut PublicContext, - from: AztecAddress, - to: AztecAddress, - amount: Field, - nonce: Field - ) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("transfer_public((Field),(Field),Field,Field)"), - [from.to_field(), to.to_field(), amount, nonce], - GasOpts::default() - ).assert_empty(); - } - - pub fn unshield( - self: Self, - context: &mut PrivateContext, - from: AztecAddress, - to: AztecAddress, - amount: Field, - nonce: Field - ) { - let _ret = context.call_private_function( - self.address, - FunctionSelector::from_signature("unshield((Field),(Field),Field,Field)"), - [from.to_field(), to.to_field(), amount, nonce] - ); - } -} - -struct TokenBridge { - address: AztecAddress, -} - -impl TokenBridge { - pub fn at(address: AztecAddress) -> Self { - Self { address } - } - - pub fn token(self: Self, context: &mut PublicContext) -> AztecAddress { - context.call_public_function( - self.address, - FunctionSelector::from_signature("get_token()"), - [], - GasOpts::default() - ).deserialize_into() - } - - pub fn exit_to_l1_public( - self: Self, - context: &mut PublicContext, - recipient: EthAddress, - amount: Field, - caller_on_l1: EthAddress, - nonce: Field - ) { - context.call_public_function( - self.address, - FunctionSelector::from_signature("exit_to_l1_public((Field),Field,(Field),Field)"), - [recipient.to_field(), amount, caller_on_l1.to_field(), nonce], - GasOpts::default() - ).assert_empty(); - } -} -// docs:end:interfaces diff --git a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr index a595616248e..32a89fcc704 100644 --- a/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/uniswap_contract/src/main.nr @@ -1,5 +1,4 @@ // docs:start:uniswap_setup -mod interfaces; mod util; // Demonstrates how to use portal contracts to swap on L1 Uniswap with funds on L2 @@ -15,7 +14,8 @@ contract Uniswap { compute_outer_authwit_hash }; - use crate::interfaces::{Token, TokenBridge}; + use dep::token::Token; + use dep::token_bridge::TokenBridge; use crate::util::{compute_swap_private_content_hash, compute_swap_public_content_hash}; #[aztec(storage)] @@ -51,25 +51,18 @@ contract Uniswap { assert_current_call_valid_authwit_public(&mut context, sender); } - let input_asset = TokenBridge::at(input_asset_bridge).token(&mut context); + let input_asset = TokenBridge::at(input_asset_bridge).get_token().call(&mut context); // Transfer funds to this contract Token::at(input_asset).transfer_public( - &mut context, sender, context.this_address(), input_amount, nonce_for_transfer_approval - ); + ).call(&mut context); // Approve bridge to burn this contract's funds and exit to L1 Uniswap Portal - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("_approve_bridge_and_exit_input_asset_to_L1((Field),(Field),Field)"), - [input_asset.to_field(), input_asset_bridge.to_field(), input_amount], - GasOpts::default() - ).assert_empty(); - + Uniswap::at(context.this_address())._approve_bridge_and_exit_input_asset_to_L1(input_asset, input_asset_bridge, input_amount).call(&mut context); // Create swap message and send to Outbox for Uniswap Portal // this ensures the integrity of what the user originally intends to do on L1. let input_asset_bridge_portal_address = get_portal_address(input_asset_bridge); @@ -115,27 +108,18 @@ contract Uniswap { ) { // Assert that user provided token address is same as expected by token bridge. // we can't directly use `input_asset_bridge.token` because that is a public method and public can't return data to private - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("_assert_token_is_same((Field),(Field))"), - [input_asset.to_field(), input_asset_bridge.to_field()] - ); + Uniswap::at(context.this_address())._assert_token_is_same(input_asset, input_asset_bridge).enqueue(&mut context); // Transfer funds to this contract Token::at(input_asset).unshield( - &mut context, context.msg_sender(), context.this_address(), input_amount, nonce_for_unshield_approval - ); + ).call(&mut context); // Approve bridge to burn this contract's funds and exit to L1 Uniswap Portal - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("_approve_bridge_and_exit_input_asset_to_L1((Field),(Field),Field)"), - [input_asset.to_field(), input_asset_bridge.to_field(), input_amount] - ); + Uniswap::at(context.this_address())._approve_bridge_and_exit_input_asset_to_L1(input_asset, input_asset_bridge, input_amount).enqueue(&mut context); // Create swap message and send to Outbox for Uniswap Portal // this ensures the integrity of what the user originally intends to do on L1. @@ -193,7 +177,11 @@ contract Uniswap { // this method is used for both private and public swaps. #[aztec(public)] #[aztec(internal)] - fn _approve_bridge_and_exit_input_asset_to_L1(token: AztecAddress, token_bridge: AztecAddress, amount: Field) { + fn _approve_bridge_and_exit_input_asset_to_L1( + token: AztecAddress, + token_bridge: AztecAddress, + amount: Field + ) { // approve bridge to burn this contract's funds (required when exiting on L1, as it burns funds on L2): let nonce_for_burn_approval = storage.nonce_for_burn_approval.read(); let selector = FunctionSelector::from_signature("burn_public((Field),Field,Field)"); @@ -212,12 +200,11 @@ contract Uniswap { // Exit to L1 Uniswap Portal ! TokenBridge::at(token_bridge).exit_to_l1_public( - &mut context, context.this_portal_address(), amount, context.this_portal_address(), nonce_for_burn_approval - ); + ).call(&mut context) } // docs:end:authwit_uniswap_set @@ -226,7 +213,7 @@ contract Uniswap { #[aztec(internal)] fn _assert_token_is_same(token: AztecAddress, token_bridge: AztecAddress) { assert( - token.eq(TokenBridge::at(token_bridge).token(&mut context)), "input_asset address is not the same as seen in the bridge contract" + token.eq(TokenBridge::at(token_bridge).get_token().call(&mut context)), "input_asset address is not the same as seen in the bridge contract" ); } // docs:end:assert_token_is_same diff --git a/noir-projects/noir-protocol-circuits/Nargo.toml b/noir-projects/noir-protocol-circuits/Nargo.toml index d3f3c3d55b0..48cc2fc96f6 100644 --- a/noir-projects/noir-protocol-circuits/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/Nargo.toml @@ -22,6 +22,7 @@ members = [ "crates/public-kernel-teardown-simulated", "crates/public-kernel-tail", "crates/public-kernel-tail-simulated", + "crates/reset-kernel-lib", "crates/rollup-lib", "crates/rollup-merge", "crates/rollup-base", diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr index bf4f3b8a048..7b188057a16 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/common.nr @@ -16,8 +16,8 @@ use dep::types::{ MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL }, hash::{ - compute_l2_to_l1_hash, compute_logs_hash, private_functions_root_from_siblings, silo_note_hash, - silo_nullifier, stdlib_recursion_verification_key_compress_native_vk + compute_l2_to_l1_hash, pedersen_hash, private_functions_root_from_siblings, + silo_note_hash, silo_nullifier, stdlib_recursion_verification_key_compress_native_vk, }, merkle_tree::check_membership, utils::{arrays::{array_length, array_to_bounded_vec, validate_array}}, @@ -37,7 +37,8 @@ pub fn validate_arrays(app_public_inputs: PrivateCircuitPublicInputs) { validate_array(app_public_inputs.private_call_stack_hashes); validate_array(app_public_inputs.public_call_stack_hashes); validate_array(app_public_inputs.new_l2_to_l1_msgs); - // encrypted_logs_hash and unencrypted_logs_hash have their own integrity checks. + validate_array(app_public_inputs.encrypted_logs_hashes); + validate_array(app_public_inputs.unencrypted_logs_hashes); } // Validate all read requests against the historical note hash tree root. @@ -106,8 +107,8 @@ pub fn initialize_end_values( public_inputs.end.public_call_stack = array_to_bounded_vec(start.public_call_stack); public_inputs.end.new_l2_to_l1_msgs = array_to_bounded_vec(start.new_l2_to_l1_msgs); - public_inputs.end.encrypted_logs_hash = start.encrypted_logs_hash; - public_inputs.end.unencrypted_logs_hash = start.unencrypted_logs_hash; + public_inputs.end.encrypted_logs_hashes = array_to_bounded_vec(start.encrypted_logs_hashes); + public_inputs.end.unencrypted_logs_hashes = array_to_bounded_vec(start.unencrypted_logs_hashes); public_inputs.end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; public_inputs.end.unencrypted_log_preimages_length = start.unencrypted_log_preimages_length; @@ -287,16 +288,13 @@ pub fn update_end_values( } } public_inputs.end.new_l2_to_l1_msgs.extend_from_bounded_vec(new_l2_to_l1_msgs_to_insert); - + // logs hashes // See the following thread if not clear: // https://discourse.aztec.network/t/proposal-forcing-the-sequencer-to-actually-submit-data-to-l1/426 - let previous_encrypted_logs_hash = public_inputs.end.encrypted_logs_hash; - let current_encrypted_logs_hash = private_call_public_inputs.encrypted_logs_hash; - public_inputs.end.encrypted_logs_hash = compute_logs_hash(previous_encrypted_logs_hash,current_encrypted_logs_hash); - let previous_unencrypted_logs_hash = public_inputs.end.unencrypted_logs_hash; - let current_unencrypted_logs_hash = private_call_public_inputs.unencrypted_logs_hash; - public_inputs.end.unencrypted_logs_hash = compute_logs_hash(previous_unencrypted_logs_hash,current_unencrypted_logs_hash); + + public_inputs.end.encrypted_logs_hashes.extend_from_bounded_vec(array_to_bounded_vec(private_call_public_inputs.encrypted_logs_hashes)); + public_inputs.end.unencrypted_logs_hashes.extend_from_bounded_vec(array_to_bounded_vec(private_call_public_inputs.unencrypted_logs_hashes)); // Add log preimages lengths from current iteration to accumulated lengths public_inputs.end.encrypted_log_preimages_length = public_inputs.end.encrypted_log_preimages_length + diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr index 22a31568e9b..84157b9b95b 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/kernel_circuit_public_inputs_composer.nr @@ -10,7 +10,8 @@ use dep::types::{ constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, grumpkin_private_key::GrumpkinPrivateKey, hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash}, @@ -29,6 +30,10 @@ struct KernelCircuitPublicInputsComposer { sorted_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], transient_note_hash_index_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], + sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX], } impl KernelCircuitPublicInputsComposer { @@ -38,7 +43,11 @@ impl KernelCircuitPublicInputsComposer { sorted_note_hashes_indexes: [u64; MAX_NEW_NOTE_HASHES_PER_TX], sorted_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], sorted_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], - transient_note_hash_index_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX] + transient_note_hash_index_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], + sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX], ) -> Self { let public_inputs = PrivateKernelCircuitPublicInputsBuilder::empty(); @@ -49,7 +58,11 @@ impl KernelCircuitPublicInputsComposer { sorted_note_hashes_indexes, sorted_nullifiers, sorted_nullifiers_indexes, - transient_note_hash_index_hints + transient_note_hash_index_hints, + sorted_encrypted_log_hashes, + sorted_encrypted_log_hashes_indexes, + sorted_unencrypted_log_hashes, + sorted_unencrypted_log_hashes_indexes, } } @@ -136,10 +149,23 @@ impl KernelCircuitPublicInputsComposer { ); self.public_inputs.end.new_nullifiers = array_to_bounded_vec(self.sorted_nullifiers); + assert_sorted_array( + accumulated_data.encrypted_logs_hashes, + self.sorted_encrypted_log_hashes, + self.sorted_encrypted_log_hashes_indexes, + asc_sort_by_counters + ); + self.public_inputs.end.encrypted_logs_hashes = array_to_bounded_vec(self.sorted_encrypted_log_hashes); + + assert_sorted_array( + accumulated_data.unencrypted_logs_hashes, + self.sorted_unencrypted_log_hashes, + self.sorted_unencrypted_log_hashes_indexes, + asc_sort_by_counters + ); + self.public_inputs.end.unencrypted_logs_hashes = array_to_bounded_vec(self.sorted_unencrypted_log_hashes); // TODO: Sort all the side effects below. self.public_inputs.end.new_l2_to_l1_msgs = array_to_bounded_vec(accumulated_data.new_l2_to_l1_msgs); - self.public_inputs.end.encrypted_logs_hash = accumulated_data.encrypted_logs_hash; - self.public_inputs.end.unencrypted_logs_hash = accumulated_data.unencrypted_logs_hash; self.public_inputs.end.encrypted_log_preimages_length = accumulated_data.encrypted_log_preimages_length; self.public_inputs.end.unencrypted_log_preimages_length = accumulated_data.unencrypted_log_preimages_length; } diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr index 0c225152de1..3c6784bdc6b 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_init.nr @@ -123,7 +123,7 @@ mod tests { address::{AztecAddress, EthAddress, compute_initialization_hash}, constants::MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, grumpkin_point::GrumpkinPoint, grumpkin_private_key::GrumpkinPrivateKey, - hash::{compute_logs_hash, stdlib_recursion_verification_key_compress_native_vk}, + hash::stdlib_recursion_verification_key_compress_native_vk, messaging::l2_to_l1_message::L2ToL1Message, tests::private_call_data_builder::PrivateCallDataBuilder, transaction::tx_request::TxRequest, utils::arrays::array_length @@ -158,12 +158,14 @@ mod tests { let mut builder = PrivateKernelInitInputsBuilder::new(); // Logs for the private call. - let encrypted_logs_hash = 16; - let encrypted_log_preimages_length = 100; - let unencrypted_logs_hash = 26; - let unencrypted_log_preimages_length = 50; - builder.private_call.set_encrypted_logs(encrypted_logs_hash, encrypted_log_preimages_length); - builder.private_call.set_unencrypted_logs(unencrypted_logs_hash, unencrypted_log_preimages_length); + let encrypted_logs_hashes = [16, 36]; + let encrypted_log_preimages_length = [100, 75]; + let unencrypted_logs_hashes = [26, 46]; + let unencrypted_log_preimages_length = [50, 25]; + builder.private_call.set_encrypted_logs(encrypted_logs_hashes[0], encrypted_log_preimages_length[0]); + builder.private_call.set_unencrypted_logs(unencrypted_logs_hashes[0], unencrypted_log_preimages_length[0]); + builder.private_call.set_encrypted_logs(encrypted_logs_hashes[1], encrypted_log_preimages_length[1]); + builder.private_call.set_unencrypted_logs(unencrypted_logs_hashes[1], unencrypted_log_preimages_length[1]); let public_inputs = builder.execute(); @@ -172,15 +174,12 @@ mod tests { assert_eq(public_inputs.end.new_nullifiers[0].value, tx_hash); // Log preimages length should increase by `(un)encrypted_log_preimages_length` from private input - assert_eq(public_inputs.end.encrypted_log_preimages_length, encrypted_log_preimages_length); - assert_eq(public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length); - - // Logs hashes should be a sha256 hash of a 0 value (the previous log hash) and the `(un)encrypted_logs_hash` from private input - let expected_encrypted_logs_hash = compute_logs_hash(0, encrypted_logs_hash); - assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); - - let expected_unencrypted_logs_hash = compute_logs_hash(0, unencrypted_logs_hash); - assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + assert_eq(public_inputs.end.encrypted_log_preimages_length, encrypted_log_preimages_length.reduce(|a, b| a + b)); + assert_eq(public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length.reduce(|a, b| a + b)); + assert_eq(public_inputs.end.encrypted_logs_hashes[0].value, encrypted_logs_hashes[0]); + assert_eq(public_inputs.end.unencrypted_logs_hashes[0].value, unencrypted_logs_hashes[0]); + assert_eq(public_inputs.end.encrypted_logs_hashes[1].value, encrypted_logs_hashes[1]); + assert_eq(public_inputs.end.unencrypted_logs_hashes[1].value, unencrypted_logs_hashes[1]); } #[test(should_fail_with = "invalid array")] @@ -257,6 +256,20 @@ mod tests { builder.failed(); } + #[test(should_fail_with = "invalid array")] + fn input_validation_malformed_arrays_logs() { + let mut builder = PrivateKernelInitInputsBuilder::new(); + + builder.private_call.public_inputs.encrypted_logs_hashes.extend_from_array( + [ + SideEffect { value: 0, counter: 0 }, + SideEffect { value: 9123, counter: 1 } + ] + ); + + builder.failed(); + } + #[test(should_fail_with="Private kernel circuit can only execute a private function")] fn private_function_is_private_false_fails() { let mut builder = PrivateKernelInitInputsBuilder::new(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr index d87964fc9ef..03425d36d98 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_inner.nr @@ -68,7 +68,7 @@ mod tests { kernel_circuit_public_inputs::PrivateKernelCircuitPublicInputs, max_block_number::MaxBlockNumber, side_effect::{SideEffect, SideEffectLinkedToNoteHash} }, - address::{AztecAddress, EthAddress}, hash::compute_logs_hash, + address::{AztecAddress, EthAddress}, messaging::l2_to_l1_message::L2ToL1Message, utils::{arrays::array_length}, tests::{private_call_data_builder::PrivateCallDataBuilder, fixture_builder::FixtureBuilder} }; @@ -447,6 +447,20 @@ mod tests { builder.failed(); } + #[test(should_fail_with = "invalid array")] + fn input_validation_malformed_arrays_logs() { + let mut builder = PrivateKernelInnerInputsBuilder::new(); + + builder.private_call.public_inputs.encrypted_logs_hashes.extend_from_array( + [ + SideEffect { value: 0, counter: 0 }, + SideEffect { value: 9123, counter: 1 } + ] + ); + + builder.failed(); + } + #[test(should_fail_with = "extend_from_bounded_vec out of bounds")] fn private_kernel_should_fail_if_aggregating_too_many_commitments() { let mut builder = PrivateKernelInnerInputsBuilder::new(); @@ -642,7 +656,7 @@ mod tests { } #[test] - fn native_logs_are_hashed_as_expected() { + fn native_logs_are_set_as_expected() { let mut builder = PrivateKernelInnerInputsBuilder::new(); // Logs for the current call stack. @@ -673,11 +687,10 @@ mod tests { public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length ); - let expected_encrypted_logs_hash = compute_logs_hash(prev_encrypted_logs_hash, encrypted_logs_hash); - assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); - - let expected_unencrypted_logs_hash = compute_logs_hash(prev_unencrypted_logs_hash, unencrypted_logs_hash); - assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + assert_eq(public_inputs.end.encrypted_logs_hashes[0].value, prev_encrypted_logs_hash); + assert_eq(public_inputs.end.unencrypted_logs_hashes[0].value, prev_unencrypted_logs_hash); + assert_eq(public_inputs.end.encrypted_logs_hashes[1].value, encrypted_logs_hash); + assert_eq(public_inputs.end.unencrypted_logs_hashes[1].value, unencrypted_logs_hash); } #[test(should_fail_with="new_note_hashes must be empty for static calls")] diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr index ac229a9beb9..5d360bb0024 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail.nr @@ -7,7 +7,7 @@ use dep::types::{ }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, grumpkin_private_key::GrumpkinPrivateKey, utils::arrays::array_length }; @@ -21,6 +21,10 @@ struct PrivateKernelTailCircuitPrivateInputs { sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], nullifier_read_request_hints: NullifierReadRequestHints, nullifier_commitment_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], + sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX], master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], } @@ -49,7 +53,11 @@ impl PrivateKernelTailCircuitPrivateInputs { self.sorted_new_note_hashes_indexes, self.sorted_new_nullifiers, self.sorted_new_nullifiers_indexes, - self.nullifier_commitment_hints + self.nullifier_commitment_hints, + self.sorted_encrypted_log_hashes, + self.sorted_encrypted_log_hashes_indexes, + self.sorted_unencrypted_log_hashes, + self.sorted_unencrypted_log_hashes_indexes, ); composer.compose().finish() } @@ -59,7 +67,7 @@ mod tests { use crate::private_kernel_tail::PrivateKernelTailCircuitPrivateInputs; use dep::reset_kernel_lib::{ tests::nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, - read_request_reset::{PendingReadHint, ReadRequestState, ReadRequestStatus} + reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} }; use dep::types::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, @@ -71,7 +79,7 @@ mod tests { side_effect::{SideEffect, SideEffectLinkedToNoteHash, Ordered} }, grumpkin_private_key::GrumpkinPrivateKey, - hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash}, + hash::{compute_note_hash_nonce, compute_unique_siloed_note_hash, accumulate_sha256}, tests::{fixture_builder::FixtureBuilder, sort::sort_get_sorted_hints}, utils::{arrays::{array_eq, array_length}}, traits::{Empty, is_empty, is_empty_array} }; @@ -154,6 +162,20 @@ mod tests { sorted_nullifier_commitment_hints[i] = sorted_new_nullifiers_indexes[self.nullifier_commitment_hints[i]]; } + let sorted = sort_get_sorted_hints( + self.previous_kernel.encrypted_logs_hashes.storage, + |a: SideEffect, b: SideEffect| a.counter < b.counter + ); + let sorted_encrypted_log_hashes = sorted.sorted_array; + let sorted_encrypted_log_hashes_indexes = sorted.sorted_index_hints; + + let sorted = sort_get_sorted_hints( + self.previous_kernel.unencrypted_logs_hashes.storage, + |a: SideEffect, b: SideEffect| a.counter < b.counter + ); + let sorted_unencrypted_log_hashes = sorted.sorted_array; + let sorted_unencrypted_log_hashes_indexes = sorted.sorted_index_hints; + let kernel = PrivateKernelTailCircuitPrivateInputs { previous_kernel: self.previous_kernel.to_private_kernel_data(), sorted_new_note_hashes, @@ -163,7 +185,11 @@ mod tests { sorted_new_nullifiers_indexes, nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), nullifier_commitment_hints: sorted_nullifier_commitment_hints, - master_nullifier_secret_keys: [GrumpkinPrivateKey::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX] + sorted_encrypted_log_hashes, + sorted_encrypted_log_hashes_indexes, + sorted_unencrypted_log_hashes, + sorted_unencrypted_log_hashes_indexes, + master_nullifier_secret_keys: [GrumpkinPrivateKey::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], }; kernel.native_private_kernel_circuit_tail() } @@ -177,6 +203,14 @@ mod tests { } } + #[test] + unconstrained fn execution_succeeded() { + let mut builder = PrivateKernelTailInputsBuilder::new(); + let public_inputs = builder.execute(); + + assert(is_empty(public_inputs.start_state)); + } + #[test] unconstrained fn native_matching_one_read_request_to_commitment_works() { let mut builder = PrivateKernelTailInputsBuilder::new(); @@ -211,6 +245,38 @@ mod tests { assert_eq(public_inputs.rollup_validation_requests.max_block_number.unwrap(), 13); } + #[test] + fn logs_are_handled_as_expected() { + let mut builder = PrivateKernelTailInputsBuilder::new(); + // Logs for the previous call stack. + let prev_encrypted_logs_hash = 80; + let prev_encrypted_log_preimages_length = 13; + let prev_unencrypted_logs_hash = 956; + let prev_unencrypted_log_preimages_length = 24; + builder.previous_kernel.set_encrypted_logs(prev_encrypted_logs_hash, prev_encrypted_log_preimages_length); + builder.previous_kernel.set_unencrypted_logs( + prev_unencrypted_logs_hash, + prev_unencrypted_log_preimages_length + ); + // Logs for the current call stack. + let unencrypted_logs_hash = 26; + let unencrypted_log_preimages_length = 50; + builder.previous_kernel.set_unencrypted_logs(unencrypted_logs_hash, unencrypted_log_preimages_length); + + let public_inputs = builder.execute(); + + assert_eq(public_inputs.end.encrypted_log_preimages_length, prev_encrypted_log_preimages_length); + assert_eq( + public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length + ); + + let expected_encrypted_logs_hash = accumulate_sha256([0, prev_encrypted_logs_hash]); + assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); + let mut expected_unencrypted_logs_hash = accumulate_sha256([0, prev_unencrypted_logs_hash]); + expected_unencrypted_logs_hash = accumulate_sha256([expected_unencrypted_logs_hash, unencrypted_logs_hash]); + assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + } + #[test] unconstrained fn one_pending_nullifier_read_request() { let mut builder = PrivateKernelTailInputsBuilder::new(); diff --git a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr index d3569bdf3b5..081219df963 100644 --- a/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr +++ b/noir-projects/noir-protocol-circuits/crates/private-kernel-lib/src/private_kernel_tail_to_public.nr @@ -7,7 +7,7 @@ use dep::types::{ }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX + MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, grumpkin_private_key::GrumpkinPrivateKey, utils::arrays::array_length }; @@ -21,6 +21,10 @@ struct PrivateKernelTailToPublicCircuitPrivateInputs { sorted_new_nullifiers_indexes: [u64; MAX_NEW_NULLIFIERS_PER_TX], nullifier_read_request_hints: NullifierReadRequestHints, nullifier_commitment_hints: [u64; MAX_NEW_NULLIFIERS_PER_TX], + sorted_encrypted_log_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_encrypted_log_hashes_indexes: [u64; MAX_ENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], + sorted_unencrypted_log_hashes_indexes: [u64; MAX_UNENCRYPTED_LOGS_PER_TX], master_nullifier_secret_keys: [GrumpkinPrivateKey; MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], } @@ -49,7 +53,11 @@ impl PrivateKernelTailToPublicCircuitPrivateInputs { self.sorted_new_note_hashes_indexes, self.sorted_new_nullifiers, self.sorted_new_nullifiers_indexes, - self.nullifier_commitment_hints + self.nullifier_commitment_hints, + self.sorted_encrypted_log_hashes, + self.sorted_encrypted_log_hashes_indexes, + self.sorted_unencrypted_log_hashes, + self.sorted_unencrypted_log_hashes_indexes, ); composer.compose_public().finish_to_public() } @@ -59,7 +67,7 @@ mod tests { use crate::private_kernel_tail_to_public::PrivateKernelTailToPublicCircuitPrivateInputs; use dep::reset_kernel_lib::{ tests::nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, - read_request_reset::{PendingReadHint, ReadRequestState, ReadRequestStatus} + reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} }; use dep::types::constants::{ MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, @@ -161,6 +169,20 @@ mod tests { sorted_nullifier_commitment_hints[i] = sorted_new_nullifiers_indexes[self.nullifier_commitment_hints[i]]; } + let sorted = sort_get_sorted_hints( + self.previous_kernel.encrypted_logs_hashes.storage, + |a: SideEffect, b: SideEffect| a.counter < b.counter + ); + let sorted_encrypted_log_hashes = sorted.sorted_array; + let sorted_encrypted_log_hashes_indexes = sorted.sorted_index_hints; + + let sorted = sort_get_sorted_hints( + self.previous_kernel.unencrypted_logs_hashes.storage, + |a: SideEffect, b: SideEffect| a.counter < b.counter + ); + let sorted_unencrypted_log_hashes = sorted.sorted_array; + let sorted_unencrypted_log_hashes_indexes = sorted.sorted_index_hints; + let kernel = PrivateKernelTailToPublicCircuitPrivateInputs { previous_kernel: self.previous_kernel.to_private_kernel_data(), sorted_new_note_hashes, @@ -170,6 +192,10 @@ mod tests { sorted_new_nullifiers_indexes, nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), nullifier_commitment_hints: sorted_nullifier_commitment_hints, + sorted_encrypted_log_hashes, + sorted_encrypted_log_hashes_indexes, + sorted_unencrypted_log_hashes, + sorted_unencrypted_log_hashes_indexes, master_nullifier_secret_keys: [GrumpkinPrivateKey::empty(); MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX], }; kernel.execute() diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr index 006b531e94d..b9d428ecd6c 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr @@ -12,7 +12,7 @@ use dep::types::{ MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - MAX_PUBLIC_DATA_READS_PER_CALL + MAX_PUBLIC_DATA_READS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL }, hash::{silo_note_hash, silo_nullifier, compute_l2_to_l1_hash, accumulate_sha256}, utils::{arrays::{array_length, array_to_bounded_vec}}, traits::{is_empty, is_empty_array} @@ -63,9 +63,9 @@ pub fn initialize_emitted_end_values( circuit_outputs.end.new_nullifiers = array_to_bounded_vec(start.new_nullifiers); circuit_outputs.end.new_l2_to_l1_msgs = array_to_bounded_vec(start.new_l2_to_l1_msgs); circuit_outputs.end.public_data_update_requests = array_to_bounded_vec(start.public_data_update_requests); - circuit_outputs.end.unencrypted_logs_hash = start.unencrypted_logs_hash; + circuit_outputs.end.unencrypted_logs_hashes = array_to_bounded_vec(start.unencrypted_logs_hashes); circuit_outputs.end.unencrypted_log_preimages_length = start.unencrypted_log_preimages_length; - circuit_outputs.end.encrypted_logs_hash = start.encrypted_logs_hash; + circuit_outputs.end.encrypted_logs_hashes = array_to_bounded_vec(start.encrypted_logs_hashes); circuit_outputs.end.encrypted_log_preimages_length = start.encrypted_log_preimages_length; } @@ -74,16 +74,13 @@ pub fn initialize_emitted_end_values( circuit_outputs.end_non_revertible.new_nullifiers = array_to_bounded_vec(start_non_revertible.new_nullifiers); circuit_outputs.end_non_revertible.new_l2_to_l1_msgs = array_to_bounded_vec(start_non_revertible.new_l2_to_l1_msgs); circuit_outputs.end_non_revertible.public_data_update_requests = array_to_bounded_vec(start_non_revertible.public_data_update_requests); - circuit_outputs.end_non_revertible.unencrypted_logs_hash = start_non_revertible.unencrypted_logs_hash; + circuit_outputs.end_non_revertible.unencrypted_logs_hashes = array_to_bounded_vec(start_non_revertible.unencrypted_logs_hashes); circuit_outputs.end_non_revertible.unencrypted_log_preimages_length = start_non_revertible.unencrypted_log_preimages_length; - circuit_outputs.end_non_revertible.encrypted_logs_hash = start_non_revertible.encrypted_logs_hash; + circuit_outputs.end_non_revertible.encrypted_logs_hashes = array_to_bounded_vec(start_non_revertible.encrypted_logs_hashes); circuit_outputs.end_non_revertible.encrypted_log_preimages_length = start_non_revertible.encrypted_log_preimages_length; - // TODO - should be propagated only in initialize_end_values() and clear them in the tail circuit. The - // max_block_number must be propagated to the rollup however as a RollupValidationRequest. let start = previous_kernel.public_inputs.validation_requests; circuit_outputs.validation_requests.max_block_number = start.for_rollup.max_block_number; - circuit_outputs.validation_requests.public_data_reads = array_to_bounded_vec(start.public_data_reads); } // Initialises the circuit outputs with the end state of the previous iteration. @@ -110,6 +107,7 @@ pub fn initialize_end_values( circuit_outputs.validation_requests.max_block_number = previous_kernel.public_inputs.validation_requests.for_rollup.max_block_number; circuit_outputs.validation_requests.nullifier_read_requests = array_to_bounded_vec(start.nullifier_read_requests); circuit_outputs.validation_requests.nullifier_non_existent_read_requests = array_to_bounded_vec(start.nullifier_non_existent_read_requests); + circuit_outputs.validation_requests.public_data_reads = array_to_bounded_vec(start.public_data_reads); } fn perform_static_call_checks(public_call: PublicCallData) { @@ -244,7 +242,8 @@ pub fn update_public_end_non_revertible_values( propagate_new_nullifiers_non_revertible(public_call, circuit_outputs); propagate_new_note_hashes_non_revertible(public_call, circuit_outputs); - propagate_new_l2_to_l1_messages(public_call, circuit_outputs); + propagate_new_l2_to_l1_messages_non_revertible(public_call, circuit_outputs); + propagate_new_unencrypted_logs_non_revertible(public_call, circuit_outputs); propagate_valid_non_revertible_public_data_update_requests(public_call, circuit_outputs); } @@ -264,7 +263,7 @@ pub fn update_public_end_values(public_call: PublicCallData, circuit_outputs: &m propagate_new_note_hashes(public_call, circuit_outputs); propagate_new_l2_to_l1_messages(public_call, circuit_outputs); - + propagate_new_unencrypted_logs(public_call, circuit_outputs); propagate_valid_public_data_update_requests(public_call, circuit_outputs); } @@ -457,7 +456,10 @@ fn propagate_new_nullifiers( circuit_outputs.end.new_nullifiers.extend_from_bounded_vec(siloed_new_nullifiers); } -fn propagate_new_l2_to_l1_messages(public_call: PublicCallData, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { +fn propagate_new_l2_to_l1_messages_non_revertible( + public_call: PublicCallData, + public_inputs: &mut PublicKernelCircuitPublicInputsBuilder +) { // new l2 to l1 messages let public_call_public_inputs = public_call.call_stack_item.public_inputs; let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; @@ -476,36 +478,61 @@ fn propagate_new_l2_to_l1_messages(public_call: PublicCallData, public_inputs: & new_l2_to_l1_msgs_to_insert.push(new_l2_to_l1_msgs) } } - public_inputs.end.new_l2_to_l1_msgs.extend_from_bounded_vec(new_l2_to_l1_msgs_to_insert); + public_inputs.end_non_revertible.new_l2_to_l1_msgs.extend_from_bounded_vec(new_l2_to_l1_msgs_to_insert); } -/** - * @brief Accumulates unencrypted logs hashes and lengths. - * @param The type of kernel input - * @param public_kernel_inputs The inputs to this iteration of the kernel circuit - * @param circuit_outputs The circuit outputs to be populated - * @note See the following thread if not clear: - * https://discourse.aztec.network/t/proposal-forcing-the-sequencer-to-actually-submit-data-to-l1/426 - * @note Used by public kernels which had previous iterations. - */ -pub fn accumulate_unencrypted_logs( - public_call: PublicCallData, - previous_unencrypted_logs_hash: Field, - previous_unencrypted_log_preimages_length: Field, - public_inputs: &mut PublicKernelCircuitPublicInputsBuilder -) { +fn propagate_new_l2_to_l1_messages(public_call: PublicCallData, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { + // new l2 to l1 messages let public_call_public_inputs = public_call.call_stack_item.public_inputs; + let storage_contract_address = public_call_public_inputs.call_context.storage_contract_address; + + let new_l2_to_l1_msgs = public_call_public_inputs.new_l2_to_l1_msgs; + let mut new_l2_to_l1_msgs_to_insert : BoundedVec = BoundedVec::new(); + for i in 0..MAX_NEW_L2_TO_L1_MSGS_PER_CALL { + let msg = new_l2_to_l1_msgs[i]; + if !is_empty(msg) { + let new_l2_to_l1_msgs = compute_l2_to_l1_hash( + storage_contract_address, + public_inputs.constants.tx_context.version, + public_inputs.constants.tx_context.chain_id, + msg + ); + new_l2_to_l1_msgs_to_insert.push(new_l2_to_l1_msgs) + } + } + public_inputs.end.new_l2_to_l1_msgs.extend_from_bounded_vec(new_l2_to_l1_msgs_to_insert); +} - let current_unencrypted_logs_hash = public_call_public_inputs.unencrypted_logs_hash; - public_inputs.end.unencrypted_logs_hash = accumulate_sha256([ - previous_unencrypted_logs_hash, - current_unencrypted_logs_hash, - ]); +pub fn propagate_new_unencrypted_logs(public_call: PublicCallData, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { + // new unencrypted logs + let new_logs = public_call.call_stack_item.public_inputs.unencrypted_logs_hashes; + // TODO(Miranda): silo logs here once we have finalised struct + let mut new_logs_to_insert : BoundedVec = BoundedVec::new(); + for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL { + let new_log = new_logs[i]; + if new_log.value != 0 { + // let siloed_new_log = something; + new_logs_to_insert.push(new_log) + } + } + public_inputs.end.unencrypted_logs_hashes.extend_from_bounded_vec(new_logs_to_insert); + public_inputs.end.unencrypted_log_preimages_length += public_call.call_stack_item.public_inputs.unencrypted_log_preimages_length; +} - // Add log preimages lengths from current iteration to accumulated lengths - let current_unencrypted_log_preimages_length = public_call_public_inputs.unencrypted_log_preimages_length; - public_inputs.end.unencrypted_log_preimages_length = - previous_unencrypted_log_preimages_length + current_unencrypted_log_preimages_length; +pub fn propagate_new_unencrypted_logs_non_revertible(public_call: PublicCallData, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { + // new unencrypted logs + let new_logs = public_call.call_stack_item.public_inputs.unencrypted_logs_hashes; + // TODO(Miranda): silo logs here once we have finalised struct + let mut new_logs_to_insert : BoundedVec = BoundedVec::new(); + for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL { + let new_log = new_logs[i]; + if new_log.value != 0 { + // let siloed_new_log = something; + new_logs_to_insert.push(new_log) + } + } + public_inputs.end_non_revertible.unencrypted_logs_hashes.extend_from_bounded_vec(new_logs_to_insert); + public_inputs.end_non_revertible.unencrypted_log_preimages_length += public_call.call_stack_item.public_inputs.unencrypted_log_preimages_length; } /** diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr index d8be35f0b39..dda4e888bdc 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_app_logic.nr @@ -42,12 +42,6 @@ impl PublicKernelAppLogicCircuitPrivateInputs { let call_request = public_inputs.end.public_call_stack.pop(); common::validate_call_against_request(self.public_call, call_request); common::update_public_end_values(self.public_call, &mut public_inputs); - common::accumulate_unencrypted_logs( - self.public_call, - self.previous_kernel.public_inputs.end.unencrypted_logs_hash, - self.previous_kernel.public_inputs.end.unencrypted_log_preimages_length, - &mut public_inputs - ); } else { let mut remaining_calls = array_to_bounded_vec(self.previous_kernel.public_inputs.end.public_call_stack); let reverted_call_request = remaining_calls.pop(); @@ -82,7 +76,7 @@ mod tests { read_request::ReadRequest, side_effect::{SideEffect, SideEffectLinkedToNoteHash} }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - hash::{compute_l2_to_l1_hash, compute_logs_hash, silo_note_hash, silo_nullifier}, + hash::{compute_l2_to_l1_hash, silo_note_hash, silo_nullifier}, messaging::l2_to_l1_message::L2ToL1Message, tests::{fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder}, utils::arrays::{array_eq, array_length} @@ -317,11 +311,9 @@ mod tests { assert_eq( public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length ); - - assert_eq(public_inputs.end.encrypted_logs_hash, prev_encrypted_logs_hash); - - let expected_unencrypted_logs_hash = compute_logs_hash(prev_unencrypted_logs_hash, unencrypted_logs_hash); - assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + assert_eq(public_inputs.end.encrypted_logs_hashes[0].value, prev_encrypted_logs_hash); + assert_eq(public_inputs.end.unencrypted_logs_hashes[0].value, prev_unencrypted_logs_hash); + assert_eq(public_inputs.end.unencrypted_logs_hashes[1].value, unencrypted_logs_hash); } #[test(should_fail_with="No contract storage update requests are allowed for static calls")] diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index b3491928e08..1703f951a53 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -49,13 +49,6 @@ impl PublicKernelSetupCircuitPrivateInputs { common::update_public_end_non_revertible_values(self.public_call, &mut public_inputs); - common::accumulate_unencrypted_logs( - self.public_call, - self.previous_kernel.public_inputs.end.unencrypted_logs_hash, - self.previous_kernel.public_inputs.end.unencrypted_log_preimages_length, - &mut public_inputs - ); - public_inputs.finish() } } @@ -76,7 +69,7 @@ mod tests { public_call_data::PublicCallData, read_request::ReadRequest }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - contrakt::storage_read::StorageRead, hash::compute_logs_hash, + contrakt::storage_read::StorageRead, tests::{fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder}, utils::{arrays::{array_eq, array_length}} }; @@ -444,25 +437,24 @@ mod tests { // Logs for the previous call stack. let prev_encrypted_logs_hash = 80; let prev_encrypted_log_preimages_length = 13; - let prev_unencrypted_logs_hash = 956; + let prev_unencrypted_logs_hash = 956; let prev_unencrypted_log_preimages_length = 24; - builder.previous_revertible.set_encrypted_logs(prev_encrypted_logs_hash, prev_encrypted_log_preimages_length); - builder.previous_revertible.set_unencrypted_logs( + builder.previous_kernel.set_encrypted_logs(prev_encrypted_logs_hash, prev_encrypted_log_preimages_length); + builder.previous_kernel.set_unencrypted_logs( prev_unencrypted_logs_hash, prev_unencrypted_log_preimages_length ); let public_inputs = builder.execute(); - - assert_eq(public_inputs.end.encrypted_log_preimages_length, prev_encrypted_log_preimages_length); + + assert_eq(public_inputs.end_non_revertible.encrypted_log_preimages_length, prev_encrypted_log_preimages_length); assert_eq( - public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length + public_inputs.end_non_revertible.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length ); - assert_eq(public_inputs.end.encrypted_logs_hash, prev_encrypted_logs_hash); - - let expected_unencrypted_logs_hash = compute_logs_hash(prev_unencrypted_logs_hash, unencrypted_logs_hash); - assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + assert_eq(public_inputs.end_non_revertible.encrypted_logs_hashes[0].value, prev_encrypted_logs_hash); + assert_eq(public_inputs.end_non_revertible.unencrypted_logs_hashes[0].value, prev_unencrypted_logs_hash); + assert_eq(public_inputs.end_non_revertible.unencrypted_logs_hashes[1].value, unencrypted_logs_hash); } #[test] diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr index 23ab1034779..c2804fd67bb 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_tail.nr @@ -1,29 +1,28 @@ use crate::common; use dep::reset_kernel_lib::{ - NullifierReadRequestHints, NullifierNonExistentReadRequestHints, reset_non_existent_read_requests, - reset_read_requests + NullifierReadRequestHints, NullifierNonExistentReadRequestHints, PublicDataReadRequestHints, + PublicValidationRequestProcessor, PublicDataHint }; use dep::types::{ abis::{ - kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PublicKernelCircuitPublicInputsBuilder}, - kernel_data::PublicKernelData, side_effect::SideEffectLinkedToNoteHash + accumulated_data::CombinedAccumulatedData, kernel_circuit_public_inputs::KernelCircuitPublicInputs, + kernel_data::PublicKernelData }, - constants::MAX_NEW_NULLIFIERS_PER_TX, - utils::{arrays::{array_length, array_merge, array_to_bounded_vec, assert_sorted_array}}, - hash::silo_nullifier, traits::is_empty + constants::MAX_PUBLIC_DATA_HINTS, + merkle_tree::{conditionally_assert_check_membership, MembershipWitness}, + partial_state_reference::PartialStateReference, utils::{arrays::array_length} }; struct PublicKernelTailCircuitPrivateInputs { previous_kernel: PublicKernelData, nullifier_read_request_hints: NullifierReadRequestHints, nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, + public_data_hints: [PublicDataHint; MAX_PUBLIC_DATA_HINTS], + public_data_read_request_hints: PublicDataReadRequestHints, + start_state: PartialStateReference, } impl PublicKernelTailCircuitPrivateInputs { - fn propagate_revert_code(self, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { - public_inputs.revert_code = self.previous_kernel.public_inputs.revert_code; - } - fn validate_inputs(self) { let previous_public_inputs = self.previous_kernel.public_inputs; assert(previous_public_inputs.needs_setup() == false, "Previous kernel needs setup"); @@ -37,106 +36,97 @@ impl PublicKernelTailCircuitPrivateInputs { ); } - fn validate_nullifier_read_requests(self, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { - let end_non_revertible = self.previous_kernel.public_inputs.end_non_revertible; - let end = self.previous_kernel.public_inputs.end; - - let requests = self.previous_kernel.public_inputs.validation_requests.nullifier_read_requests; - - let pending_nullifiers = array_merge(end_non_revertible.new_nullifiers, end.new_nullifiers); - - let hints = self.nullifier_read_request_hints; - - let nullifier_tree_root = public_inputs.constants.historical_header.state.partial.nullifier_tree.root; - - let unverified_nullifier_read_requests = reset_read_requests( - requests, - pending_nullifiers, - hints.read_request_statuses, - hints.pending_read_hints, - hints.settled_read_hints, - nullifier_tree_root - ); - - assert( - unverified_nullifier_read_requests.len() == 0, "All nullifier read requests must be verified" - ); - } - - fn validate_nullifier_non_existent_read_requests(self, public_inputs: &mut PublicKernelCircuitPublicInputsBuilder) { - let end_non_revertible = self.previous_kernel.public_inputs.end_non_revertible; - let end = self.previous_kernel.public_inputs.end; - - // The values of the read requests here need to be siloed. - // Notice that it's not the case for regular read requests, which can be run between two kernel iterations, and will to be verified against unsiloed pending values. - let mut read_requests = self.previous_kernel.public_inputs.validation_requests.nullifier_non_existent_read_requests; - for i in 0..read_requests.len() { - let read_request = read_requests[i]; - if !is_empty(read_request) { - read_requests[i].value = silo_nullifier(read_request.contract_address, read_request.value); + fn validate_public_data_hints(self) { + let public_data_hints = self.public_data_hints; + let public_data_tree_root = self.start_state.public_data_tree.root; + for i in 0..public_data_hints.len() { + let hint = public_data_hints[i]; + // We only need to check leaf_slot to decide if a (non-)membership check is required. + // It will fail if a PublicDataHint with 0 leaf_slot is used to verify a non-empty public read or write. + if hint.leaf_slot != 0 { + let exists_in_tree = hint.leaf_slot == hint.leaf_preimage.slot; + if exists_in_tree { + assert( + hint.value == hint.leaf_preimage.value, "Hinted public data value does not match the value in leaf preimage" + ); + } else { + assert(hint.value == 0, "Value must be 0 for non-existent public data"); + } + + conditionally_assert_check_membership( + hint.leaf_slot, + exists_in_tree, + hint.leaf_preimage, + MembershipWitness { leaf_index: hint.membership_witness.leaf_index, sibling_path: hint.membership_witness.sibling_path }, + public_data_tree_root + ); } } + } - let nullifier_tree_root = public_inputs.constants.historical_header.state.partial.nullifier_tree.root; - - let hints = self.nullifier_non_existent_read_request_hints; - - let pending_nullifiers = array_merge(end_non_revertible.new_nullifiers, end.new_nullifiers); - assert_sorted_array( - pending_nullifiers, - hints.sorted_pending_values, - hints.sorted_pending_value_index_hints, - |a: SideEffectLinkedToNoteHash, b: SideEffectLinkedToNoteHash| a.value.lt(b.value) - ); - let sorted_pending_nullifiers = array_to_bounded_vec(hints.sorted_pending_values); - - reset_non_existent_read_requests( - read_requests, - hints.non_membership_hints, - nullifier_tree_root, - sorted_pending_nullifiers, - hints.next_pending_value_indices - ); + fn propagate_accumulated_data(self) -> CombinedAccumulatedData { + let previous_public_inputs = self.previous_kernel.public_inputs; + // TODO: Sort the combined data. + CombinedAccumulatedData::combine( + previous_public_inputs.end_non_revertible, + previous_public_inputs.end + ) } pub fn public_kernel_tail(self) -> KernelCircuitPublicInputs { - let mut public_inputs = PublicKernelCircuitPublicInputsBuilder::empty(); - self.validate_inputs(); - self.propagate_revert_code(&mut public_inputs); - - common::initialize_emitted_end_values(self.previous_kernel, &mut public_inputs); + self.validate_public_data_hints(); - self.validate_nullifier_read_requests(&mut public_inputs); + let previous_public_inputs = self.previous_kernel.public_inputs; + let request_processor = PublicValidationRequestProcessor::new( + previous_public_inputs, + self.nullifier_read_request_hints, + self.nullifier_non_existent_read_request_hints, + self.start_state.nullifier_tree.root, + self.public_data_read_request_hints, + self.public_data_hints + ); + request_processor.validate(); - self.validate_nullifier_non_existent_read_requests(&mut public_inputs); + let end = self.propagate_accumulated_data(); - public_inputs.finish_tail() + KernelCircuitPublicInputs { + aggregation_object: previous_public_inputs.aggregation_object, + rollup_validation_requests: previous_public_inputs.validation_requests.for_rollup, + end, + constants: previous_public_inputs.constants, + start_state: self.start_state, + revert_code: previous_public_inputs.revert_code + } } } mod tests { - use crate::{public_kernel_tail::PublicKernelTailCircuitPrivateInputs}; + use crate::public_kernel_tail::PublicKernelTailCircuitPrivateInputs; use dep::reset_kernel_lib::{ tests::{ nullifier_non_existent_read_request_hints_builder::NullifierNonExistentReadRequestHintsBuilder, - nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder + nullifier_read_request_hints_builder::NullifierReadRequestHintsBuilder, + public_data_read_request_hints_builder::PublicDataReadRequestHintsBuilder }, - read_request_reset::{PendingReadHint, ReadRequestState, ReadRequestStatus} + PublicDataHint, reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} }; use dep::types::{ abis::{ - kernel_circuit_public_inputs::{KernelCircuitPublicInputs, PublicKernelCircuitPublicInputsBuilder}, - kernel_data::PublicKernelData, nullifier_leaf_preimage::NullifierLeafPreimage + kernel_circuit_public_inputs::KernelCircuitPublicInputs, kernel_data::PublicKernelData, + nullifier_leaf_preimage::NullifierLeafPreimage, membership_witness::PublicDataMembershipWitness }, constants::{ - MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, - NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT + MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_PUBLIC_DATA_HINTS, + MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT, + NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT, + PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT }, - hash::silo_nullifier, + hash::{silo_nullifier, accumulate_sha256}, + public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, tests::{fixture_builder::FixtureBuilder, merkle_tree_utils::NonEmptyMerkleTree}, - utils::arrays::array_merge + partial_state_reference::PartialStateReference, utils::arrays::array_merge }; fn build_nullifier_tree() -> NonEmptyMerkleTree { @@ -151,11 +141,33 @@ mod tests { ) } + fn get_settled_public_data_leaves() -> [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX] { + let mut settled_public_data_leaves = [PublicDataTreeLeafPreimage::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX]; + settled_public_data_leaves[0] = PublicDataTreeLeafPreimage { slot: 22, value: 200, next_slot: 33, next_index: 1 }; + settled_public_data_leaves[1] = PublicDataTreeLeafPreimage { slot: 33, value: 300, next_slot: 0, next_index: 0 }; + settled_public_data_leaves[2] = PublicDataTreeLeafPreimage { slot: 11, value: 100, next_slot: 22, next_index: 0 }; + settled_public_data_leaves + } + + fn build_public_data_tree() -> NonEmptyMerkleTree { + let settled_public_data_leaves = get_settled_public_data_leaves(); + NonEmptyMerkleTree::new( + settled_public_data_leaves.map(|preimage: PublicDataTreeLeafPreimage| preimage.hash()), + [0; PUBLIC_DATA_TREE_HEIGHT], + [0; PUBLIC_DATA_TREE_HEIGHT - PUBLIC_DATA_SUBTREE_HEIGHT], + [0; PUBLIC_DATA_SUBTREE_HEIGHT] + ) + } + struct PublicKernelTailCircuitPrivateInputsBuilder { previous_kernel: FixtureBuilder, previous_revertible: FixtureBuilder, nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder, nullifier_non_existent_read_request_hints_builder: NullifierNonExistentReadRequestHintsBuilder, + public_data_read_request_hints_builder: PublicDataReadRequestHintsBuilder, + public_data_hints: BoundedVec, + public_data_tree: NonEmptyMerkleTree, + start_state: PartialStateReference, } impl PublicKernelTailCircuitPrivateInputsBuilder { @@ -168,7 +180,11 @@ mod tests { previous_kernel, previous_revertible, nullifier_read_request_hints_builder: NullifierReadRequestHintsBuilder::new(MAX_NULLIFIER_READ_REQUESTS_PER_TX), - nullifier_non_existent_read_request_hints_builder + nullifier_non_existent_read_request_hints_builder, + public_data_read_request_hints_builder: PublicDataReadRequestHintsBuilder::new(MAX_PUBLIC_DATA_READS_PER_TX), + public_data_hints: BoundedVec::new(), + public_data_tree: NonEmptyMerkleTree::empty(), + start_state: PartialStateReference::empty() }; builder.set_nullifiers_for_non_existent_read_request_hints(); builder @@ -176,8 +192,17 @@ mod tests { pub fn with_nullifier_tree(&mut self) -> Self { let nullifier_tree = build_nullifier_tree(); - self.previous_kernel.historical_header.state.partial.nullifier_tree.root = nullifier_tree.get_root(); self.nullifier_non_existent_read_request_hints_builder.set_nullifier_tree(nullifier_tree); + let tree_root = nullifier_tree.get_root(); + self.start_state.nullifier_tree.root = tree_root; + self.previous_kernel.historical_header.state.partial.nullifier_tree.root = tree_root; + *self + } + + pub fn with_public_data_tree(&mut self) -> Self { + let public_data_tree = build_public_data_tree(); + self.public_data_tree = public_data_tree; + self.start_state.public_data_tree.root = public_data_tree.get_root(); *self } @@ -236,6 +261,37 @@ mod tests { self.nullifier_non_existent_read_request_hints_builder.add_value_read(siloed_nullifier); } + pub fn add_public_data_hint_for_settled_public_data(&mut self, leaf_index: u64) { + let leaf_preimage = get_settled_public_data_leaves()[leaf_index]; + let membership_witness = PublicDataMembershipWitness { leaf_index: leaf_index as Field, sibling_path: self.public_data_tree.get_sibling_path(leaf_index) }; + let hint = PublicDataHint { + leaf_slot: leaf_preimage.slot, + value: leaf_preimage.value, + override_counter: 0, + membership_witness, + leaf_preimage + }; + self.public_data_hints.push(hint); + } + + pub fn add_public_data_hint_for_non_existent_public_data(&mut self, leaf_slot: Field, low_leaf_index: u64) { + let leaf_preimage = get_settled_public_data_leaves()[low_leaf_index]; + let membership_witness = PublicDataMembershipWitness { + leaf_index: low_leaf_index as Field, + sibling_path: self.public_data_tree.get_sibling_path(low_leaf_index) + }; + let hint = PublicDataHint { leaf_slot, value: 0, override_counter: 0, membership_witness, leaf_preimage }; + self.public_data_hints.push(hint); + } + + pub fn add_pending_public_data_read_request(&mut self, public_date_update_request_index: u64) { + let read_request_index = self.previous_kernel.add_read_request_for_pending_public_data(public_date_update_request_index); + let hint_index = self.public_data_read_request_hints_builder.pending_read_hints.len(); + let hint = PendingReadHint { read_request_index, pending_value_index: public_date_update_request_index }; + self.public_data_read_request_hints_builder.pending_read_hints.push(hint); + self.public_data_read_request_hints_builder.read_request_statuses[read_request_index] = ReadRequestStatus { state: ReadRequestState.PENDING, hint_index }; + } + fn sync_counters(&mut self) { let counter_non_revertible = self.previous_kernel.counter; let counter_revertible = self.previous_revertible.counter; @@ -253,7 +309,10 @@ mod tests { let kernel = PublicKernelTailCircuitPrivateInputs { previous_kernel, nullifier_read_request_hints: self.nullifier_read_request_hints_builder.to_hints(), - nullifier_non_existent_read_request_hints: self.nullifier_non_existent_read_request_hints_builder.to_hints() + nullifier_non_existent_read_request_hints: self.nullifier_non_existent_read_request_hints_builder.to_hints(), + public_data_hints: self.public_data_hints.storage, + public_data_read_request_hints: self.public_data_read_request_hints_builder.to_hints(), + start_state: self.start_state }; kernel.public_kernel_tail() @@ -275,6 +334,38 @@ mod tests { // TODO: Check the values in public inputs. } + #[test] + fn logs_are_handled_as_expected() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); + // Logs for the previous call stack. + let prev_encrypted_logs_hash = 80; + let prev_encrypted_log_preimages_length = 13; + let prev_unencrypted_logs_hash = 956; + let prev_unencrypted_log_preimages_length = 24; + builder.previous_revertible.set_encrypted_logs(prev_encrypted_logs_hash, prev_encrypted_log_preimages_length); + builder.previous_revertible.set_unencrypted_logs( + prev_unencrypted_logs_hash, + prev_unencrypted_log_preimages_length + ); + // Logs for the current call stack. + let unencrypted_logs_hash = 26; + let unencrypted_log_preimages_length = 50; + builder.previous_revertible.set_unencrypted_logs(unencrypted_logs_hash, unencrypted_log_preimages_length); + + let public_inputs = builder.execute(); + + assert_eq(public_inputs.end.encrypted_log_preimages_length, prev_encrypted_log_preimages_length); + assert_eq( + public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length + ); + + let expected_encrypted_logs_hash = accumulate_sha256([0, prev_encrypted_logs_hash]); + assert_eq(public_inputs.end.encrypted_logs_hash, expected_encrypted_logs_hash); + let mut expected_unencrypted_logs_hash = accumulate_sha256([0, prev_unencrypted_logs_hash]); + expected_unencrypted_logs_hash = accumulate_sha256([expected_unencrypted_logs_hash, unencrypted_logs_hash]); + assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + } + #[test] unconstrained fn one_pending_nullifier_read_request() { let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); @@ -356,6 +447,95 @@ mod tests { builder.read_non_existent_nullifier(1); + builder.failed(); + } + + #[test] + unconstrained fn validate_public_data_hints() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_public_data_tree(); + + builder.add_public_data_hint_for_settled_public_data(1); + builder.add_public_data_hint_for_settled_public_data(0); + builder.add_public_data_hint_for_settled_public_data(2); + builder.succeeded(); } + + #[test(should_fail_with="Hinted public data value does not match the value in leaf preimage")] + unconstrained fn validate_public_data_hints_failed_mismatch_value() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_public_data_tree(); + + builder.add_public_data_hint_for_settled_public_data(1); + + let mut hint = builder.public_data_hints.pop(); + hint.value += 1; + builder.public_data_hints.push(hint); + + builder.failed(); + } + + #[test] + unconstrained fn validate_public_data_hints_uninitialized_value() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_public_data_tree(); + + builder.add_public_data_hint_for_non_existent_public_data(25, 0); + + builder.succeeded(); + } + + #[test(should_fail_with="Value must be 0 for non-existent public data")] + unconstrained fn validate_public_data_hints_failed_non_zero_uninitialized_value() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new().with_public_data_tree(); + + builder.add_public_data_hint_for_non_existent_public_data(25, 0); + + let mut hint = builder.public_data_hints.pop(); + hint.value = 1; + builder.public_data_hints.push(hint); + + builder.failed(); + } + + #[test] + unconstrained fn pending_public_data_read_requests() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); + + builder.previous_kernel.append_public_data_update_requests(3); + + builder.add_pending_public_data_read_request(1); + builder.add_pending_public_data_read_request(0); + builder.add_pending_public_data_read_request(2); + + builder.succeeded(); + } + + #[test(should_fail_with="Hinted slot of data write does not match read request")] + unconstrained fn pending_public_data_read_requests_failed_wrong_write_index() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); + + builder.previous_kernel.append_public_data_update_requests(2); + + builder.add_pending_public_data_read_request(1); + + let mut hint = builder.public_data_read_request_hints_builder.pending_read_hints.pop(); + hint.pending_value_index += 1; + builder.public_data_read_request_hints_builder.pending_read_hints.push(hint); + + builder.failed(); + } + + #[test(should_fail_with="Hinted value of data write does not match read request")] + unconstrained fn pending_public_data_read_requests_failed_wrong_write_value() { + let mut builder = PublicKernelTailCircuitPrivateInputsBuilder::new(); + + builder.previous_kernel.append_public_data_update_requests(1); + + builder.add_pending_public_data_read_request(0); + + let mut public_data_write = builder.previous_kernel.public_data_update_requests.pop(); + public_data_write.new_value += 1; + builder.previous_kernel.public_data_update_requests.push(public_data_write); + + builder.failed(); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index 70600fda54c..67b89c28167 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -46,15 +46,6 @@ impl PublicKernelTeardownCircuitPrivateInputs { common::update_public_end_non_revertible_values(self.public_call, &mut public_inputs); - if public_inputs.revert_code == 0 { - common::accumulate_unencrypted_logs( - self.public_call, - self.previous_kernel.public_inputs.end.unencrypted_logs_hash, - self.previous_kernel.public_inputs.end.unencrypted_log_preimages_length, - &mut public_inputs - ); - } - public_inputs.finish() } } @@ -74,7 +65,7 @@ mod tests { public_data_update_request::PublicDataUpdateRequest }, address::{AztecAddress, EthAddress}, contract_class_id::ContractClassId, - contrakt::storage_read::StorageRead, hash::compute_logs_hash, + contrakt::storage_read::StorageRead, tests::{fixture_builder::FixtureBuilder, public_call_data_builder::PublicCallDataBuilder}, utils::{arrays::{array_eq, array_length}} }; @@ -348,23 +339,21 @@ mod tests { let prev_encrypted_log_preimages_length = 13; let prev_unencrypted_logs_hash = 956; let prev_unencrypted_log_preimages_length = 24; - builder.previous_revertible.set_encrypted_logs(prev_encrypted_logs_hash, prev_encrypted_log_preimages_length); - builder.previous_revertible.set_unencrypted_logs( + builder.previous_kernel.set_encrypted_logs(prev_encrypted_logs_hash, prev_encrypted_log_preimages_length); + builder.previous_kernel.set_unencrypted_logs( prev_unencrypted_logs_hash, prev_unencrypted_log_preimages_length ); let public_inputs = builder.execute(); - assert_eq(public_inputs.end.encrypted_log_preimages_length, prev_encrypted_log_preimages_length); + assert_eq(public_inputs.end_non_revertible.encrypted_log_preimages_length, prev_encrypted_log_preimages_length); assert_eq( - public_inputs.end.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length + public_inputs.end_non_revertible.unencrypted_log_preimages_length, unencrypted_log_preimages_length + prev_unencrypted_log_preimages_length ); - - assert_eq(public_inputs.end.encrypted_logs_hash, prev_encrypted_logs_hash); - - let expected_unencrypted_logs_hash = compute_logs_hash(prev_unencrypted_logs_hash, unencrypted_logs_hash); - assert_eq(public_inputs.end.unencrypted_logs_hash, expected_unencrypted_logs_hash); + assert_eq(public_inputs.end_non_revertible.encrypted_logs_hashes[0].value, prev_encrypted_logs_hash); + assert_eq(public_inputs.end_non_revertible.unencrypted_logs_hashes[0].value, prev_unencrypted_logs_hash); + assert_eq(public_inputs.end_non_revertible.unencrypted_logs_hashes[1].value, unencrypted_logs_hash); } #[test(should_fail_with="Public call cannot be reverted")] diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr index a156e40f1a6..8a7ffb5e38b 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/lib.nr @@ -1,12 +1,15 @@ -use non_existent_read_request_reset::reset_non_existent_read_requests; use nullifier_non_existent_read_request_reset::NullifierNonExistentReadRequestHints; use nullifier_read_request_reset::NullifierReadRequestHints; use private_validation_request_processor::PrivateValidationRequestProcessor; -use read_request_reset::reset_read_requests; +use public_data_read_request_reset::PublicDataReadRequestHints; +use public_validation_request_processor::PublicValidationRequestProcessor; +use types::public_data_hint::PublicDataHint; -mod non_existent_read_request_reset; mod nullifier_non_existent_read_request_reset; mod nullifier_read_request_reset; mod private_validation_request_processor; -mod read_request_reset; +mod public_data_read_request_reset; +mod public_validation_request_processor; +mod reset; mod tests; +mod types; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_non_existent_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_non_existent_read_request_reset.nr index cc76145b18e..5f9f7548782 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_non_existent_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_non_existent_read_request_reset.nr @@ -1,7 +1,7 @@ -use crate::non_existent_read_request_reset::{NonMembershipHint}; +use crate::reset::non_existent_read_request::NonMembershipHint; use dep::types::{ abis::{nullifier_leaf_preimage::NullifierLeafPreimage, side_effect::SideEffectLinkedToNoteHash}, - merkle_tree::{MembershipWitness}, + merkle_tree::MembershipWitness, constants::{MAX_NEW_NULLIFIERS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT} }; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr index cb2e0abc875..de2da03dc8c 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/nullifier_read_request_reset.nr @@ -1,5 +1,5 @@ // This will be moved to a separate Read Request Reset Circuit. -use crate::read_request_reset::{PendingReadHint, ReadRequestStatus, ReadValueHint, SettledReadHint}; +use crate::reset::read_request::{PendingReadHint, ReadRequestStatus, ReadValueHint, SettledReadHint}; use dep::types::{ abis::{nullifier_leaf_preimage::NullifierLeafPreimage}, constants::{MAX_NULLIFIER_READ_REQUESTS_PER_TX, NULLIFIER_TREE_HEIGHT}, @@ -44,7 +44,7 @@ struct NullifierReadRequestHints { mod tests { use crate::nullifier_read_request_reset::NullifierSettledReadHint; - use crate::read_request_reset::{PendingReadHint, ReadRequestState, ReadRequestStatus, reset_read_requests}; + use crate::reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus, reset_read_requests}; use dep::types::{ address::AztecAddress, abis::{ diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr index 9f60134dd45..469a4d6d9bf 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/private_validation_request_processor.nr @@ -1,4 +1,4 @@ -use crate::{nullifier_read_request_reset::NullifierReadRequestHints, read_request_reset::reset_read_requests}; +use crate::{nullifier_read_request_reset::NullifierReadRequestHints, reset::read_request::reset_read_requests}; use dep::types::{ abis::{side_effect::{SideEffect, SideEffectLinkedToNoteHash}, validation_requests::ValidationRequests}, constants::{ diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_reset.nr new file mode 100644 index 00000000000..7c6b6634074 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_data_read_request_reset.nr @@ -0,0 +1,9 @@ +use crate::reset::{mutable_data_read_request::LeafDataReadHint, read_request::{PendingReadHint, ReadRequestStatus}}; +use dep::types::constants::MAX_PUBLIC_DATA_READS_PER_TX; + +// The MAX_PUBLIC_DATA_READS_PER_TX for pending_read_hints and leaf_data_read_hints can change if we create various circuits that deal with different number of reads. +struct PublicDataReadRequestHints { + read_request_statuses: [ReadRequestStatus; MAX_PUBLIC_DATA_READS_PER_TX], + pending_read_hints: [PendingReadHint; MAX_PUBLIC_DATA_READS_PER_TX], + leaf_data_read_hints: [LeafDataReadHint; MAX_PUBLIC_DATA_READS_PER_TX], +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr new file mode 100644 index 00000000000..4a74f99fd5b --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/public_validation_request_processor.nr @@ -0,0 +1,127 @@ +use crate::{ + reset::{ + non_existent_read_request::reset_non_existent_read_requests, + mutable_data_read_request::reset_mutable_data_read_requests, read_request::reset_read_requests +}, + nullifier_read_request_reset::NullifierReadRequestHints, + nullifier_non_existent_read_request_reset::NullifierNonExistentReadRequestHints, + public_data_read_request_reset::PublicDataReadRequestHints, types::public_data_hint::PublicDataHint +}; +use dep::types::{ + abis::{ + kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs, + public_data_update_request::PublicDataUpdateRequest, side_effect::SideEffectLinkedToNoteHash, + validation_requests::ValidationRequests +}, + constants::{MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX}, + hash::silo_nullifier, traits::is_empty, + utils::arrays::{array_merge, array_to_bounded_vec, assert_sorted_array} +}; + +struct PublicValidationRequestProcessor { + validation_requests: ValidationRequests, + pending_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], + pending_public_data_writes: [PublicDataUpdateRequest; MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], + nullifier_read_request_hints: NullifierReadRequestHints, + nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, + nullifier_tree_root: Field, + public_data_read_request_hints: PublicDataReadRequestHints, + public_data_hints: [PublicDataHint; N], +} + +impl PublicValidationRequestProcessor { + pub fn new( + public_inputs: PublicKernelCircuitPublicInputs, + nullifier_read_request_hints: NullifierReadRequestHints, + nullifier_non_existent_read_request_hints: NullifierNonExistentReadRequestHints, + nullifier_tree_root: Field, + public_data_read_request_hints: PublicDataReadRequestHints, + public_data_hints: [PublicDataHint; N] + ) -> Self { + let end_non_revertible = public_inputs.end_non_revertible; + let end = public_inputs.end; + + let pending_nullifiers = array_merge(end_non_revertible.new_nullifiers, end.new_nullifiers); + + let pending_public_data_writes = array_merge( + end_non_revertible.public_data_update_requests, + end.public_data_update_requests + ); + + PublicValidationRequestProcessor { + validation_requests: public_inputs.validation_requests, + pending_nullifiers, + pending_public_data_writes, + nullifier_read_request_hints, + nullifier_non_existent_read_request_hints, + nullifier_tree_root, + public_data_read_request_hints, + public_data_hints + } + } + + pub fn validate(self) { + self.validate_nullifier_read_requests(); + self.validate_nullifier_non_existent_read_requests(); + self.validate_public_data_read_requests(); + } + + fn validate_nullifier_read_requests(self) { + let requests = self.validation_requests.nullifier_read_requests; + let hints = self.nullifier_read_request_hints; + let unverified_nullifier_read_requests = reset_read_requests( + requests, + self.pending_nullifiers, + hints.read_request_statuses, + hints.pending_read_hints, + hints.settled_read_hints, + self.nullifier_tree_root + ); + assert( + unverified_nullifier_read_requests.len() == 0, "All nullifier read requests must be verified" + ); + } + + fn validate_nullifier_non_existent_read_requests(self) { + // The values of the read requests here need to be siloed. + // Notice that it's not the case for regular read requests, which can be run between two kernel iterations, and will to be verified against unsiloed pending values. + let mut read_requests = self.validation_requests.nullifier_non_existent_read_requests; + for i in 0..read_requests.len() { + let read_request = read_requests[i]; + if !is_empty(read_request) { + read_requests[i].value = silo_nullifier(read_request.contract_address, read_request.value); + } + } + + let hints = self.nullifier_non_existent_read_request_hints; + + assert_sorted_array( + self.pending_nullifiers, + hints.sorted_pending_values, + hints.sorted_pending_value_index_hints, + |a: SideEffectLinkedToNoteHash, b: SideEffectLinkedToNoteHash| a.value.lt(b.value) + ); + let sorted_pending_nullifiers = array_to_bounded_vec(hints.sorted_pending_values); + + reset_non_existent_read_requests( + read_requests, + hints.non_membership_hints, + self.nullifier_tree_root, + sorted_pending_nullifiers, + hints.next_pending_value_indices + ); + } + + fn validate_public_data_read_requests(self) { + let hints = self.public_data_read_request_hints; + + reset_mutable_data_read_requests( + self.validation_requests.public_data_reads, + hints.read_request_statuses, + self.pending_public_data_writes, + self.public_data_hints, + hints.pending_read_hints, + hints.leaf_data_read_hints + ); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset.nr new file mode 100644 index 00000000000..8b98420b3cd --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset.nr @@ -0,0 +1,3 @@ +mod mutable_data_read_request; +mod non_existent_read_request; +mod read_request; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/mutable_data_read_request.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/mutable_data_read_request.nr new file mode 100644 index 00000000000..a86ab40f20d --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/mutable_data_read_request.nr @@ -0,0 +1,320 @@ +use crate::reset::read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus}; +use dep::types::{ + abis::{public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest}, + traits::{Empty, is_empty} +}; + +trait LeafDataHint { + fn leaf_slot(self) -> Field; + fn value(self) -> Field; + fn override_counter(self) -> u32; +} + +struct LeafDataReadHint { + read_request_index: u64, + data_hint_index: u64, +} + +impl LeafDataReadHint { + pub fn nada(read_request_len: u64) -> Self { + LeafDataReadHint { read_request_index: read_request_len, data_hint_index: 0 } + } +} + +fn validate_pending_read_requests( + read_requests: [PublicDataRead; READ_REQUEST_LEN], + data_writes: [PublicDataUpdateRequest; PENDING_VALUE_LEN], + hints: [PendingReadHint; NUM_PENDING_READS] +) { + for i in 0..NUM_PENDING_READS { + let read_request_index = hints[i].read_request_index; + if read_request_index != READ_REQUEST_LEN { + let read_request = read_requests[read_request_index]; + let pending_value = data_writes[hints[i].pending_value_index]; + assert( + read_request.leaf_slot.eq(pending_value.leaf_slot), "Hinted slot of data write does not match read request" + ); + assert( + read_request.value.eq(pending_value.new_value), "Hinted value of data write does not match read request" + ); + // TODO: Add counters and verify the following: + // assert( + // read_request.counter > pending_value.counter, "Read request counter must be greater than the counter of the data write" + // ); + // assert((read_request.counter < pending_value.next_counter) | (pending_value.next_counter == 0), "Read request counter must be less than the counter of the next data write"); + } + } +} + +fn validate_leaf_data_read_requests( + read_requests: [PublicDataRead; READ_REQUEST_LEN], + leaf_data_hints: [H; NUM_LEAF_DATA_HINTS], + hints: [LeafDataReadHint; NUM_LEAF_DATA_READS] +) where H: LeafDataHint { + for i in 0..NUM_LEAF_DATA_READS { + let read_request_index = hints[i].read_request_index; + if read_request_index != READ_REQUEST_LEN { + let read_request = read_requests[read_request_index]; + let data_hint = leaf_data_hints[hints[i].data_hint_index]; + assert( + read_request.leaf_slot == data_hint.leaf_slot(), "Hinted slot does not match read request" + ); + assert(read_request.value == data_hint.value(), "Hinted value does not match read request"); + // TODO: Add counters and verify the following: + // assert((read_request.counter < data_hint.override_counter) | (data_hint.override_counter == 0), "Hinted leaf is overridden before the read request"); + } + } +} + +fn ensure_all_read_requests_are_verified( + read_requests: [PublicDataRead; READ_REQUEST_LEN], + read_request_statuses: [ReadRequestStatus; READ_REQUEST_LEN], + pending_read_hints: [PendingReadHint; NUM_PENDING_READS], + leaf_data_read_hints: [LeafDataReadHint; NUM_LEAF_DATA_READS] +) { + for i in 0..READ_REQUEST_LEN { + let read_request = read_requests[i]; + if !is_empty(read_request) { + let status = read_request_statuses[i]; + if status.state == ReadRequestState.PENDING { + assert( + pending_read_hints[status.hint_index].read_request_index == i, "Hinted pending read request does not match status" + ); + } else if status.state == ReadRequestState.SETTLED { + assert( + leaf_data_read_hints[status.hint_index].read_request_index == i, "Hinted settled read request does not match status" + ); + } else { + assert(false, "Read request status must be PENDING or SETTLED"); + } + } + } +} + +pub fn reset_mutable_data_read_requests( + read_requests: [PublicDataRead; READ_REQUEST_LEN], + read_request_statuses: [ReadRequestStatus; READ_REQUEST_LEN], + data_writes: [PublicDataUpdateRequest; PENDING_VALUE_LEN], + leaf_data_hints: [H; NUM_LEAF_DATA_HINTS], + pending_read_hints: [PendingReadHint; NUM_PENDING_READS], + leaf_data_read_hints: [LeafDataReadHint; NUM_LEAF_DATA_READS] +) where H: LeafDataHint { + validate_pending_read_requests(read_requests, data_writes, pending_read_hints); + + validate_leaf_data_read_requests(read_requests, leaf_data_hints, leaf_data_read_hints); + + ensure_all_read_requests_are_verified( + read_requests, + read_request_statuses, + pending_read_hints, + leaf_data_read_hints + ); +} + +mod tests { + use crate::reset::{ + mutable_data_read_request::{ + ensure_all_read_requests_are_verified, reset_mutable_data_read_requests, LeafDataHint, + LeafDataReadHint, validate_pending_read_requests, validate_leaf_data_read_requests + }, + read_request::{PendingReadHint, ReadRequestState, ReadRequestStatus} + }; + use dep::types::{abis::{public_data_read::PublicDataRead, public_data_update_request::PublicDataUpdateRequest}}; + + struct TestLeafDataHint { + leaf_slot: Field, + value: Field, + } + + impl LeafDataHint for TestLeafDataHint { + fn leaf_slot(self) -> Field { + self.leaf_slot + } + + fn value(self) -> Field { + self.value + } + + fn override_counter(_self: Self) -> u32 { + 0 + } + } + + global data_writes = [ + PublicDataUpdateRequest { leaf_slot: 22, new_value: 200 }, + PublicDataUpdateRequest { leaf_slot: 11, new_value: 100 }, + PublicDataUpdateRequest { leaf_slot: 33, new_value: 300 }, + PublicDataUpdateRequest { leaf_slot: 44, new_value: 400 } + ]; + + global leaf_data_hints = [ + TestLeafDataHint { leaf_slot: 7, value: 70 }, + TestLeafDataHint { leaf_slot: 6, value: 60 }, + TestLeafDataHint { leaf_slot: 5, value: 50 }, + ]; + + fn create_pending_read_requests(data_write_indices: [u64; N]) -> ([PublicDataRead; N], [PendingReadHint; N]) { + let read_requests = data_write_indices.map( + |data_write_index: u64| PublicDataRead { leaf_slot: data_writes[data_write_index].leaf_slot, value: data_writes[data_write_index].new_value } + ); + let mut hints = BoundedVec::new(); + for i in 0..N { + hints.push(PendingReadHint { read_request_index: i, pending_value_index: data_write_indices[i] }); + } + (read_requests, hints.storage) + } + + fn create_leaf_data_read_requests(data_hint_indices: [u64; N]) -> ([PublicDataRead; N], [LeafDataReadHint; N]) { + let read_requests = data_hint_indices.map( + |data_hint_index: u64| PublicDataRead { leaf_slot: leaf_data_hints[data_hint_index].leaf_slot, value: leaf_data_hints[data_hint_index].value } + ); + let mut hints = BoundedVec::new(); + for i in 0..N { + hints.push(LeafDataReadHint { read_request_index: i, data_hint_index: data_hint_indices[i] }); + } + (read_requests, hints.storage) + } + + #[test] + fn reset_pending_reads_succeeds() { + let (read_requests, hints) = create_pending_read_requests([2, 0, 1, 3]); + validate_pending_read_requests(read_requests, data_writes, hints); + } + + #[test] + fn reset_pending_reads_repeated_values() { + let (read_requests, hints) = create_pending_read_requests([1, 0, 0, 1]); + validate_pending_read_requests(read_requests, data_writes, hints); + } + + #[test] + fn reset_pending_reads_skips_nada() { + let read_requests = [PublicDataRead { leaf_slot: 88, value: 9999 }]; + let hints = [PendingReadHint::nada(1)]; + validate_pending_read_requests(read_requests, data_writes, hints); + } + + #[test(should_fail_with="Hinted slot of data write does not match read request")] + fn reset_pending_reads_wrong_slot_fails() { + let mut (read_requests, hints) = create_pending_read_requests([1]); + hints[0].pending_value_index = 0; + validate_pending_read_requests(read_requests, data_writes, hints); + } + + #[test(should_fail_with="Hinted value of data write does not match read request")] + fn reset_pending_reads_wrong_value_fails() { + let mut (read_requests, hints) = create_pending_read_requests([1]); + read_requests[0].value += 1; + validate_pending_read_requests(read_requests, data_writes, hints); + } + + #[test] + fn reset_leaf_data_reads_succeeds() { + let (read_requests, hints) = create_leaf_data_read_requests([2, 1, 0]); + validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + } + + #[test] + fn reset_leaf_data_reads_repeated_values() { + let (read_requests, hints) = create_leaf_data_read_requests([1, 0, 1, 0]); + validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + } + + #[test] + fn reset_leaf_data_reads_skips_nada() { + let read_requests = [PublicDataRead { leaf_slot: 88, value: 9999 }]; + let hints = [LeafDataReadHint::nada(1)]; + validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + } + + #[test(should_fail_with=""Hinted slot does not match read request")] + fn reset_leaf_reads_wrong_slot_fails() { + let mut (read_requests, hints) = create_leaf_data_read_requests([1]); + hints[0].data_hint_index = 0; + validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + } + + #[test(should_fail_with=""Hinted value does not match read request")] + fn reset_leaf_reads_wrong_value_fails() { + let mut (read_requests, hints) = create_leaf_data_read_requests([1]); + read_requests[0].value += 1; + validate_leaf_data_read_requests(read_requests, leaf_data_hints, hints); + } + + #[test] + fn ensure_all_read_requests_are_verified_succeeds() { + let mut (pending_read_requests, pending_read_hints) = create_pending_read_requests([1]); + let mut (leaf_read_requests, leaf_data_read_hints) = create_leaf_data_read_requests([0, 1]); + let read_requests = [leaf_read_requests[0], pending_read_requests[0], leaf_read_requests[1]]; + pending_read_hints[0].read_request_index = 1; + leaf_data_read_hints[1].read_request_index = 2; + + let statuses = [ + ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 0 }, + ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 0 }, + ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 1 } + ]; + + ensure_all_read_requests_are_verified( + read_requests, + statuses, + pending_read_hints, + leaf_data_read_hints + ); + } + + #[test(should_fail_with="Hinted pending read request does not match status")] + fn ensure_all_read_requests_are_verified_wrong_pending_hint_index_fails() { + let (read_requests, hints) = create_pending_read_requests([0, 1]); + let statuses = [ + ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 0 }, + ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 0 } + ]; + ensure_all_read_requests_are_verified(read_requests, statuses, hints, []); + } + + #[test(should_fail_with="Hinted settled read request does not match status")] + fn ensure_all_read_requests_are_verified_wrong_leaf_hint_index_fails() { + let (read_requests, hints) = create_leaf_data_read_requests([0, 1]); + let statuses = [ + ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 0 }, + ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 0 } + ]; + ensure_all_read_requests_are_verified(read_requests, statuses, [], hints); + } + + #[test(should_fail_with="Read request status must be PENDING or SETTLED")] + fn ensure_all_read_requests_are_verified_wrong_status_fails() { + let (read_requests, hints) = create_leaf_data_read_requests([0]); + let statuses = [ReadRequestStatus { state: ReadRequestState.NADA, hint_index: 0 }]; + ensure_all_read_requests_are_verified(read_requests, statuses, [], hints); + } + + #[test] + fn reset_mutable_data_read_requests_succeeds() { + let mut (pending_read_requests, pending_read_hints) = create_pending_read_requests([3, 1]); + let mut (leaf_read_requests, leaf_data_read_hints) = create_leaf_data_read_requests([0, 1]); + let read_requests = [ + leaf_read_requests[0], pending_read_requests[0], pending_read_requests[1], leaf_read_requests[1] + ]; + pending_read_hints[0].read_request_index = 1; + pending_read_hints[1].read_request_index = 2; + leaf_data_read_hints[1].read_request_index = 3; + + let statuses = [ + ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 0 }, + ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 0 }, + ReadRequestStatus { state: ReadRequestState.PENDING, hint_index: 1 }, + ReadRequestStatus { state: ReadRequestState.SETTLED, hint_index: 1 } + ]; + + reset_mutable_data_read_requests( + read_requests, + statuses, + data_writes, + leaf_data_hints, + pending_read_hints, + leaf_data_read_hints + ); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/non_existent_read_request_reset.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr similarity index 94% rename from noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/non_existent_read_request_reset.nr rename to noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr index 4beeee665ae..afb50e68ce5 100644 --- a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/non_existent_read_request_reset.nr +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/reset/non_existent_read_request.nr @@ -86,7 +86,7 @@ pub fn reset_non_existent_read_requests, + leaf_data_read_hints: BoundedVec, +} + +impl PublicDataReadRequestHintsBuilder { + pub fn new(read_request_len: u64) -> Self { + PublicDataReadRequestHintsBuilder { + read_request_statuses: [ReadRequestStatus::empty(); MAX_PUBLIC_DATA_READS_PER_TX], + pending_read_hints: BoundedVec { storage: [PendingReadHint::nada(read_request_len); MAX_PUBLIC_DATA_READS_PER_TX], len: 0 }, + leaf_data_read_hints: BoundedVec { storage: [LeafDataReadHint::nada(read_request_len); MAX_PUBLIC_DATA_READS_PER_TX], len: 0 } + } + } + + pub fn to_hints(self) -> PublicDataReadRequestHints { + PublicDataReadRequestHints { + read_request_statuses: self.read_request_statuses, + pending_read_hints: self.pending_read_hints.storage, + leaf_data_read_hints: self.leaf_data_read_hints.storage + } + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types.nr new file mode 100644 index 00000000000..aa16f1fe678 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types.nr @@ -0,0 +1 @@ +mod public_data_hint; diff --git a/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types/public_data_hint.nr b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types/public_data_hint.nr new file mode 100644 index 00000000000..28a3eb74cb0 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/reset-kernel-lib/src/types/public_data_hint.nr @@ -0,0 +1,27 @@ +use crate::reset::{mutable_data_read_request::LeafDataHint}; +use dep::types::{ + abis::membership_witness::PublicDataMembershipWitness, + public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage +}; + +struct PublicDataHint { + leaf_slot: Field, + value: Field, + override_counter: u32, + membership_witness: PublicDataMembershipWitness, // Should be MembershipWitness when we can handle generics when converting to ts types. + leaf_preimage: PublicDataTreeLeafPreimage, +} + +impl LeafDataHint for PublicDataHint { + fn leaf_slot(self) -> Field { + self.leaf_slot + } + + fn value(self) -> Field { + self.value + } + + fn override_counter(self) -> u32 { + self.override_counter + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr index a9e9e772f59..db3a8cddfb0 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/base/base_rollup_inputs.nr @@ -29,7 +29,7 @@ use dep::types::{ }, mocked::{AggregationObject, Proof}, partial_state_reference::PartialStateReference, public_data_tree_leaf::PublicDataTreeLeaf, - public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, + public_data_tree_leaf_preimage::PublicDataTreeLeafPreimage, traits::is_empty, utils::{field::{full_field_less_than, full_field_greater_than}, uint256::U256} }; @@ -66,6 +66,8 @@ impl BaseRollupInputs { == self.constants.global_variables.version, "kernel version does not match the rollup version" ); + self.validate_kernel_start_state(); + let rollup_validation_requests = self.kernel_data.public_inputs.rollup_validation_requests; // Verify the max block number @@ -177,18 +179,22 @@ impl BaseRollupInputs { calculate_subtree_root(leaves.map(|leaf:NullifierLeafPreimage| leaf.hash())) } - fn validate_and_process_public_state(self) -> AppendOnlyTreeSnapshot { - // TODO(#2521) - data read validation should happen against the current state of the tx and not the start state. - // Blocks all interesting usecases that read and write to the same public state in the same tx. - // https://aztecprotocol.slack.com/archives/C02M7VC7TN0/p1695809629015719?thread_ts=1695653252.007339&cid=C02M7VC7TN0 - - // Process public data reads and public data update requests for left input - // validate_public_data_reads( - // self.start_public_data_tree_root, - // self.kernel_data[0].public_inputs.end.public_data_reads, - // 0, - // self.new_public_data_reads_sibling_paths); + fn validate_kernel_start_state(self) { + let kernel_state = self.kernel_data.public_inputs.start_state; + if !is_empty(kernel_state) { + assert( + kernel_state.note_hash_tree.eq(self.start.note_hash_tree), "Mismatch start state for note hash tree" + ); + assert( + kernel_state.nullifier_tree.eq(self.start.nullifier_tree), "Mismatch start state for nullifier tree" + ); + assert( + kernel_state.public_data_tree.eq(self.start.public_data_tree), "Mismatch start state for public data tree" + ); + } + } + fn validate_and_process_public_state(self) -> AppendOnlyTreeSnapshot { let end_public_data_tree_snapshot = insert_public_data_update_requests( self.start.public_data_tree, self.kernel_data.public_inputs.end.public_data_update_requests.map( @@ -318,43 +324,6 @@ fn insert_public_data_update_requests( ) } -fn validate_public_data_reads( - tree_root: Field, - public_data_reads: [PublicDataRead; MAX_PUBLIC_DATA_READS_PER_TX], - public_data_reads_preimages: [PublicDataTreeLeafPreimage; MAX_PUBLIC_DATA_READS_PER_TX], - public_data_reads_witnesses: [PublicDataMembershipWitness; MAX_PUBLIC_DATA_READS_PER_TX] -) { - for i in 0..MAX_PUBLIC_DATA_READS_PER_TX { - let read = public_data_reads[i]; - let low_preimage = public_data_reads_preimages[i]; - let witness = public_data_reads_witnesses[i]; - - let is_low_empty = low_preimage.is_empty(); - let is_exact = low_preimage.slot == read.leaf_slot; - - let is_less_than_slot = full_field_less_than(low_preimage.slot, read.leaf_slot); - let is_next_greater_than = full_field_less_than(read.leaf_slot, low_preimage.next_slot); - let is_in_range = is_less_than_slot - & (is_next_greater_than | ((low_preimage.next_index == 0) & (low_preimage.next_slot == 0))); - - if (!read.is_empty()) { - assert(!is_low_empty, "public data read is not empty but low preimage is empty"); - if is_in_range { - assert_eq(read.value, 0, "low leaf for public data read is in range but value is not zero"); - } else { - assert(is_exact, "low leaf for public data read is invalid"); - assert_eq(read.value, low_preimage.value, "low leaf for public data has different value"); - } - assert_check_membership( - low_preimage.hash(), - witness.leaf_index, - witness.sibling_path, - tree_root - ); - } - } -} - #[test] fn consistent_not_hash_subtree_width() { assert_eq( diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr index 93f148a675a..2e23a804ce1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/combined_accumulated_data.nr @@ -1,4 +1,5 @@ use crate::{ + hash::compute_tx_logs_hash, abis::{ accumulated_data::public_accumulated_data::PublicAccumulatedData, public_data_update_request::PublicDataUpdateRequest, @@ -30,15 +31,18 @@ struct CombinedAccumulatedData { } impl CombinedAccumulatedData { - pub fn recombine(non_revertible: PublicAccumulatedData, revertible: PublicAccumulatedData) -> Self { + pub fn combine(non_revertible: PublicAccumulatedData, revertible: PublicAccumulatedData) -> Self { + // TODO(Miranda): Hash here or elsewhere? + let encrypted_logs_hash = compute_tx_logs_hash(array_merge(non_revertible.encrypted_logs_hashes, revertible.encrypted_logs_hashes)); + let unencrypted_logs_hash = compute_tx_logs_hash(array_merge(non_revertible.unencrypted_logs_hashes, revertible.unencrypted_logs_hashes)); CombinedAccumulatedData { new_note_hashes: array_merge(non_revertible.new_note_hashes, revertible.new_note_hashes).map(|n: SideEffect| n.value), new_nullifiers: array_merge(non_revertible.new_nullifiers, revertible.new_nullifiers).map(|n: SideEffectLinkedToNoteHash| n.value), new_l2_to_l1_msgs: revertible.new_l2_to_l1_msgs, - encrypted_logs_hash: revertible.encrypted_logs_hash, - unencrypted_logs_hash: revertible.unencrypted_logs_hash, - encrypted_log_preimages_length: revertible.encrypted_log_preimages_length, - unencrypted_log_preimages_length: revertible.unencrypted_log_preimages_length, + encrypted_logs_hash: encrypted_logs_hash, + unencrypted_logs_hash: unencrypted_logs_hash, + encrypted_log_preimages_length: non_revertible.encrypted_log_preimages_length + revertible.encrypted_log_preimages_length, + unencrypted_log_preimages_length: non_revertible.unencrypted_log_preimages_length + revertible.unencrypted_log_preimages_length, public_data_update_requests: array_merge( non_revertible.public_data_update_requests, revertible.public_data_update_requests diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr index 708f52a5785..2fc4064125a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data.nr @@ -1,7 +1,8 @@ use crate::{abis::{call_request::CallRequest, gas::Gas, side_effect::{SideEffect, SideEffectLinkedToNoteHash}}}; use crate::constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX + MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }; struct PrivateAccumulatedData { @@ -9,8 +10,8 @@ struct PrivateAccumulatedData { new_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], - encrypted_logs_hash: Field, - unencrypted_logs_hash: Field, + encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr index f4952927111..464fdda2079 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/private_accumulated_data_builder.nr @@ -1,4 +1,5 @@ use crate::{ + hash::compute_tx_logs_hash, abis::{ gas::Gas, accumulated_data::{ @@ -12,7 +13,7 @@ use crate::{ constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, traits::Empty }; @@ -22,8 +23,8 @@ struct PrivateAccumulatedDataBuilder { new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, - encrypted_logs_hash: Field, - unencrypted_logs_hash: Field, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -42,8 +43,8 @@ impl PrivateAccumulatedDataBuilder { new_note_hashes: self.new_note_hashes.storage, new_nullifiers: self.new_nullifiers.storage, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, - encrypted_logs_hash: self.encrypted_logs_hash, - unencrypted_logs_hash: self.unencrypted_logs_hash, + encrypted_logs_hashes: self.encrypted_logs_hashes.storage, + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, private_call_stack: self.private_call_stack.storage, @@ -53,12 +54,16 @@ impl PrivateAccumulatedDataBuilder { } pub fn to_combined(self) -> CombinedAccumulatedData { + // TODO(Miranda): Hash here or elsewhere? + let encrypted_logs_hash = compute_tx_logs_hash(self.encrypted_logs_hashes.storage); + let unencrypted_logs_hash = compute_tx_logs_hash(self.unencrypted_logs_hashes.storage); + CombinedAccumulatedData { new_note_hashes: self.new_note_hashes.storage.map(|n: SideEffect| n.value), new_nullifiers: self.new_nullifiers.storage.map(|n: SideEffectLinkedToNoteHash| n.value), new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, - encrypted_logs_hash: self.encrypted_logs_hash, - unencrypted_logs_hash: self.unencrypted_logs_hash, + encrypted_logs_hash: encrypted_logs_hash, + unencrypted_logs_hash: unencrypted_logs_hash, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, public_data_update_requests: [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], @@ -81,6 +86,7 @@ impl PrivateAccumulatedDataBuilder { revertible_builder.new_note_hashes.push(note_hash); } } + for i in 0..MAX_NEW_NULLIFIERS_PER_TX { let nullifier = self.new_nullifiers.storage[i]; if nullifier.counter < min_revertible_side_effect_counter { @@ -99,11 +105,28 @@ impl PrivateAccumulatedDataBuilder { } } + for i in 0..MAX_ENCRYPTED_LOGS_PER_TX { + let encrypted_logs_hash = self.encrypted_logs_hashes.storage[i]; + if encrypted_logs_hash.counter < min_revertible_side_effect_counter { + non_revertible_builder.encrypted_logs_hashes.push(encrypted_logs_hash); + } else { + revertible_builder.encrypted_logs_hashes.push(encrypted_logs_hash); + } + } + + for i in 0..MAX_UNENCRYPTED_LOGS_PER_TX { + let unencrypted_logs_hash = self.unencrypted_logs_hashes.storage[i]; + if unencrypted_logs_hash.counter < min_revertible_side_effect_counter { + non_revertible_builder.unencrypted_logs_hashes.push(unencrypted_logs_hash); + } else { + revertible_builder.unencrypted_logs_hashes.push(unencrypted_logs_hash); + } + } + revertible_builder.new_l2_to_l1_msgs = self.new_l2_to_l1_msgs; - revertible_builder.encrypted_logs_hash = self.encrypted_logs_hash; - revertible_builder.unencrypted_logs_hash = self.unencrypted_logs_hash; + // TODO(1165): Once we have individual lens, split here revertible_builder.encrypted_log_preimages_length = self.encrypted_log_preimages_length; - revertible_builder.unencrypted_log_preimages_length= self.unencrypted_log_preimages_length; + revertible_builder.unencrypted_log_preimages_length = self.unencrypted_log_preimages_length; (non_revertible_builder.finish(), revertible_builder.finish()) } @@ -198,8 +221,8 @@ impl Empty for PrivateAccumulatedDataBuilder { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), - encrypted_logs_hash: 0, - unencrypted_logs_hash: 0, + encrypted_logs_hashes: BoundedVec::new(), + unencrypted_logs_hashes: BoundedVec::new(), encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, private_call_stack: BoundedVec::new(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr index 813d86ec94b..595f1aa8193 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data.nr @@ -5,7 +5,8 @@ use crate::{ }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, traits::Empty }; @@ -15,8 +16,8 @@ struct PublicAccumulatedData { new_nullifiers: [SideEffectLinkedToNoteHash; MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [Field; MAX_NEW_L2_TO_L1_MSGS_PER_TX], - encrypted_logs_hash: Field, - unencrypted_logs_hash: Field, + encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_TX], // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -36,8 +37,8 @@ impl Empty for PublicAccumulatedData { new_note_hashes: [SideEffect::empty(); MAX_NEW_NOTE_HASHES_PER_TX], new_nullifiers: [SideEffectLinkedToNoteHash::empty(); MAX_NEW_NULLIFIERS_PER_TX], new_l2_to_l1_msgs: [0; MAX_NEW_L2_TO_L1_MSGS_PER_TX], - encrypted_logs_hash: 0, - unencrypted_logs_hash: 0, + encrypted_logs_hashes: [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_TX], + unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_TX], encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, public_data_update_requests: [PublicDataUpdateRequest::empty(); MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX], diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr index 02bb488ff27..e66601a3418 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/accumulated_data/public_accumulated_data_builder.nr @@ -6,7 +6,8 @@ use crate::{ }, constants::{ MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, - MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, traits::Empty }; @@ -16,8 +17,8 @@ struct PublicAccumulatedDataBuilder { new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, - encrypted_logs_hash: Field, - unencrypted_logs_hash: Field, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -37,8 +38,8 @@ impl PublicAccumulatedDataBuilder { new_note_hashes: self.new_note_hashes.storage, new_nullifiers: self.new_nullifiers.storage, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, - encrypted_logs_hash: self.encrypted_logs_hash, - unencrypted_logs_hash: self.unencrypted_logs_hash, + encrypted_logs_hashes: self.encrypted_logs_hashes.storage, + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, public_data_update_requests: self.public_data_update_requests.storage, @@ -54,8 +55,8 @@ impl Empty for PublicAccumulatedDataBuilder { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), - encrypted_logs_hash: 0, - unencrypted_logs_hash: 0, + encrypted_logs_hashes: BoundedVec::new(), + unencrypted_logs_hashes: BoundedVec::new(), encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, public_data_update_requests: BoundedVec::new(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr index b15b68d2365..41100691cbc 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/kernel_circuit_public_inputs.nr @@ -1,6 +1,9 @@ -use crate::abis::{ +use crate::{ + abis::{ accumulated_data::CombinedAccumulatedData, combined_constant_data::CombinedConstantData, validation_requests::RollupValidationRequests +}, + partial_state_reference::PartialStateReference }; use crate::mocked::AggregationObject; @@ -9,5 +12,6 @@ struct KernelCircuitPublicInputs { rollup_validation_requests: RollupValidationRequests, end: CombinedAccumulatedData, constants: CombinedConstantData, + start_state: PartialStateReference, revert_code: u8, } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr index 5aa04bfc44f..b4fc5217621 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/private_kernel_circuit_public_inputs_builder.nr @@ -8,8 +8,7 @@ use crate::{ }, validation_requests::validation_requests_builder::ValidationRequestsBuilder }, -mocked::AggregationObject, -traits::Empty + mocked::AggregationObject, partial_state_reference::PartialStateReference, traits::Empty }; struct PrivateKernelCircuitPublicInputsBuilder { @@ -37,6 +36,7 @@ impl PrivateKernelCircuitPublicInputsBuilder { rollup_validation_requests: self.validation_requests.to_rollup(), end: self.end.to_combined(), constants: self.constants, + start_state: PartialStateReference::empty(), revert_code: 0 } } @@ -65,4 +65,4 @@ impl Empty for PrivateKernelCircuitPublicInputsBuilder { constants: CombinedConstantData::empty(), } } -} \ No newline at end of file +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr index 6d3dc6fefc4..5a0ff151e9b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/kernel_circuit_public_inputs/public_kernel_circuit_public_inputs_builder.nr @@ -2,14 +2,10 @@ use crate::{ abis::{ accumulated_data::{CombinedAccumulatedData, PublicAccumulatedDataBuilder}, combined_constant_data::CombinedConstantData, - kernel_circuit_public_inputs::{ - kernel_circuit_public_inputs::KernelCircuitPublicInputs, - public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs -}, + kernel_circuit_public_inputs::{public_kernel_circuit_public_inputs::PublicKernelCircuitPublicInputs}, validation_requests::ValidationRequestsBuilder }, -mocked::AggregationObject, -traits::Empty + mocked::AggregationObject, traits::Empty }; struct PublicKernelCircuitPublicInputsBuilder { @@ -35,17 +31,6 @@ impl PublicKernelCircuitPublicInputsBuilder { revert_code: self.revert_code } } - - pub fn finish_tail(self) -> KernelCircuitPublicInputs { - KernelCircuitPublicInputs { - aggregation_object: self.aggregation_object, - rollup_validation_requests: self.validation_requests.to_rollup(), - // TODO: Sort by counters. - end: CombinedAccumulatedData::recombine(self.end_non_revertible.finish(), self.end.finish()), - constants: self.constants, - revert_code: self.revert_code - } - } } impl Empty for PublicKernelCircuitPublicInputsBuilder { @@ -59,4 +44,4 @@ impl Empty for PublicKernelCircuitPublicInputsBuilder { revert_code: 0 as u8, } } -} \ No newline at end of file +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr index df4227c518c..45b7f67c493 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_call_stack_item.nr @@ -85,6 +85,6 @@ fn empty_hash() { let hash = item.hash(); // Value from private_call_stack_item.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x243b1b69ea529d158803cc7a16b52293c5e5f2a1859337e3f69e4b20f55c6fb6; + let test_data_empty_hash = 0x24185d8e88fe796dec6e400f3d6c7572cefd85cea80591f268f08a9350992c48; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr index 637e8ac2e99..0e49b29d76d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/private_circuit_public_inputs.nr @@ -9,7 +9,8 @@ use crate::{ MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, - PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS + PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, + GENERATOR_INDEX__PRIVATE_CIRCUIT_PUBLIC_INPUTS, MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL }, header::Header, hash::pedersen_hash, messaging::l2_to_l1_message::L2ToL1Message, traits::{Deserialize, Hash, Serialize, Empty}, utils::reader::Reader @@ -37,8 +38,8 @@ struct PrivateCircuitPublicInputs { start_side_effect_counter : u32, end_side_effect_counter : u32, - encrypted_logs_hash: Field, - unencrypted_logs_hash: Field, + encrypted_logs_hashes: [SideEffect; MAX_ENCRYPTED_LOGS_PER_CALL], + unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_CALL], // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -71,8 +72,8 @@ impl Eq for PrivateCircuitPublicInputs { (self.new_l2_to_l1_msgs == other.new_l2_to_l1_msgs) & (self.start_side_effect_counter == other.start_side_effect_counter) & (self.end_side_effect_counter == other.end_side_effect_counter) & - (self.encrypted_logs_hash == other.encrypted_logs_hash) & - (self.unencrypted_logs_hash == other.unencrypted_logs_hash) & + (self.encrypted_logs_hashes == other.encrypted_logs_hashes) & + (self.unencrypted_logs_hashes == other.unencrypted_logs_hashes) & (self.encrypted_log_preimages_length == other.encrypted_log_preimages_length) & (self.unencrypted_log_preimages_length == other.unencrypted_log_preimages_length) & self.historical_header.eq(other.historical_header) & @@ -114,8 +115,12 @@ impl Serialize for PrivateCircuitPublicInp } fields.push(self.start_side_effect_counter as Field); fields.push(self.end_side_effect_counter as Field); - fields.push(self.encrypted_logs_hash); - fields.push(self.unencrypted_logs_hash); + for i in 0..MAX_ENCRYPTED_LOGS_PER_CALL{ + fields.extend_from_array(self.encrypted_logs_hashes[i].serialize()); + } + for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{ + fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + } fields.push(self.encrypted_log_preimages_length); fields.push(self.unencrypted_log_preimages_length); fields.extend_from_array(self.historical_header.serialize()); @@ -148,8 +153,8 @@ impl Deserialize for PrivateCircuitPublicI new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]), start_side_effect_counter: reader.read() as u32, end_side_effect_counter: reader.read() as u32, - encrypted_logs_hash: reader.read() as Field, - unencrypted_logs_hash: reader.read() as Field, + encrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_CALL]), + unencrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]), encrypted_log_preimages_length: reader.read(), unencrypted_log_preimages_length: reader.read(), historical_header: reader.read_struct(Header::deserialize), @@ -187,8 +192,8 @@ impl Empty for PrivateCircuitPublicInputs { new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter : 0 as u32, end_side_effect_counter : 0 as u32, - encrypted_logs_hash: 0, - unencrypted_logs_hash: 0, + encrypted_logs_hashes: [SideEffect::empty(); MAX_ENCRYPTED_LOGS_PER_CALL], + unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, historical_header: Header::empty(), @@ -210,8 +215,7 @@ fn serialization_of_empty() { fn empty_hash() { let inputs = PrivateCircuitPublicInputs::empty(); let hash = inputs.hash(); - // Value from private_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x02e09d8c4897d560bd4caf05ab45fa22e1d4a251bf5b5e0448310a7f40f7a0b8; + let test_data_empty_hash = 0x24ea9ab3fc039778bef8e7212f6a09feec1019db19b449333b523a08b812ee88; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr index 1a5f9dd9be8..7bafc07b37d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_call_stack_item.nr @@ -69,7 +69,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: true, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item request hash" test - let test_data_call_stack_item_request_hash = 0x12c634ebadf4209e2def6cac0753f151422faf11237dc4f136bc17a84c8c2d76; + let test_data_call_stack_item_request_hash = 0x134d01b778664dbc1ffa953008ce28f72b0cb258533776f10df59a59d791e972; assert_eq(call_stack_item.hash(), test_data_call_stack_item_request_hash); } @@ -87,7 +87,7 @@ mod tests { let call_stack_item = PublicCallStackItem { contract_address, public_inputs, is_execution_request: false, function_data }; // Value from public_call_stack_item.test.ts "Computes a callstack item hash" test - let test_data_call_stack_item_hash = 0x0864975afc9bec7eb7ec5b5608bbef648ec9afead1bbe986d0af148e3c944b9b; + let test_data_call_stack_item_hash = 0x0c0d60d424315af5f106a802b250c27c613a9ec1c0f583c6ad806cf22fe66a13; assert_eq(call_stack_item.hash(), test_data_call_stack_item_hash); } } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr index 7e96d95c411..6ac77bcc55d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/public_circuit_public_inputs.nr @@ -8,8 +8,9 @@ use crate::{ MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS, - PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, + GENERATOR_INDEX__PUBLIC_CIRCUIT_PUBLIC_INPUTS, PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, + MAX_UNENCRYPTED_LOGS_PER_CALL }, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, hash::pedersen_hash, header::Header, messaging::l2_to_l1_message::L2ToL1Message, @@ -36,7 +37,7 @@ struct PublicCircuitPublicInputs{ start_side_effect_counter: u32, end_side_effect_counter: u32, - unencrypted_logs_hash: Field, + unencrypted_logs_hashes: [SideEffect; MAX_UNENCRYPTED_LOGS_PER_CALL], // Here so that the gas cost of this request can be measured by circuits, without actually needing to feed in the // variable-length data. @@ -93,7 +94,9 @@ impl Serialize for PublicCircuitPublicInput fields.push(self.start_side_effect_counter as Field); fields.push(self.end_side_effect_counter as Field); - fields.push(self.unencrypted_logs_hash); + for i in 0..MAX_UNENCRYPTED_LOGS_PER_CALL{ + fields.extend_from_array(self.unencrypted_logs_hashes[i].serialize()); + } fields.push(self.unencrypted_log_preimages_length); fields.extend_from_array(self.historical_header.serialize()); fields.push(self.prover_address.to_field()); @@ -121,7 +124,7 @@ impl Deserialize for PublicCircuitPublicInp new_l2_to_l1_msgs: reader.read_struct_array(L2ToL1Message::deserialize, [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL]), start_side_effect_counter: reader.read() as u32, end_side_effect_counter: reader.read() as u32, - unencrypted_logs_hash: reader.read() as Field, + unencrypted_logs_hashes: reader.read_struct_array(SideEffect::deserialize, [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL]), unencrypted_log_preimages_length: reader.read(), historical_header: reader.read_struct(Header::deserialize), prover_address: reader.read_struct(AztecAddress::deserialize), @@ -156,7 +159,7 @@ impl Empty for PublicCircuitPublicInputs { new_l2_to_l1_msgs: [L2ToL1Message::empty(); MAX_NEW_L2_TO_L1_MSGS_PER_CALL], start_side_effect_counter: 0 as u32, end_side_effect_counter: 0 as u32, - unencrypted_logs_hash: 0, + unencrypted_logs_hashes: [SideEffect::empty(); MAX_UNENCRYPTED_LOGS_PER_CALL], unencrypted_log_preimages_length: 0, historical_header: Header::empty(), prover_address: AztecAddress::zero(), @@ -180,6 +183,6 @@ fn empty_hash() { let hash = inputs.hash(); // Value from public_circuit_public_inputs.test.ts "computes empty item hash" test - let test_data_empty_hash = 0x00147d3d2cde08ee1046bf73cb6664c2bdf11b43c5dca0e72f4137f354bdad25; + let test_data_empty_hash = 0x1092820bc987359300ff136abf020d58218e1b3484e03d756c76e81ac56ccbf7; assert_eq(hash, test_data_empty_hash); } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr index df67b7f6dc2..359fae794ba 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/address/partial_address.nr @@ -4,9 +4,11 @@ use crate::{ aztec_address::AztecAddress }, constants::GENERATOR_INDEX__PARTIAL_ADDRESS, contract_class_id::ContractClassId, - hash::pedersen_hash, traits::ToField + hash::pedersen_hash, traits::{ToField, FromField, Serialize, Deserialize} }; +global PARTIAL_ADDRESS_LENGTH = 1; + // Partial address struct PartialAddress { inner : Field @@ -18,6 +20,18 @@ impl ToField for PartialAddress { } } +impl Serialize for PartialAddress { + fn serialize(self: Self) -> [Field; PARTIAL_ADDRESS_LENGTH] { + [self.to_field()] + } +} + +impl Deserialize for PartialAddress { + fn deserialize(fields: [Field; PARTIAL_ADDRESS_LENGTH]) -> Self { + PartialAddress { inner: fields[0] } + } +} + impl PartialAddress { pub fn from_field(field: Field) -> Self { Self { inner: field } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 96f1a6dcdd2..4d040a0db25 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -33,6 +33,12 @@ global MAX_NOTE_HASH_READ_REQUESTS_PER_CALL: u64 = 32; global MAX_NULLIFIER_READ_REQUESTS_PER_CALL: u64 = 2; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL: u64 = 2; global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL: u64 = 1; +// Note: if changing enc logs per call value by n, change PRIVATE_CALL_STACK_ITEM_LENGTH and PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH by 2n +// and change DEPLOYER_CONTRACT_ADDRESS to new value +global MAX_ENCRYPTED_LOGS_PER_CALL: u64 = 4; +// Note: if changing unenc logs per call value by n, change PRIVATE_CALL_STACK_ITEM_LENGTH, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, and PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH by 2n +// and change DEPLOYER_CONTRACT_ADDRESS to new value +global MAX_UNENCRYPTED_LOGS_PER_CALL: u64 = 4; // "PER TRANSACTION" CONSTANTS global MAX_NEW_NOTE_HASHES_PER_TX: u64 = 64; @@ -46,10 +52,15 @@ global MAX_NOTE_HASH_READ_REQUESTS_PER_TX: u64 = 128; global MAX_NULLIFIER_READ_REQUESTS_PER_TX: u64 = 8; // Change it to a larger value when there's a seperate reset circuit. global MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX: u64 = 8; global MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX: u64 = 4; +global MAX_ENCRYPTED_LOGS_PER_TX: u64 = 8; +global MAX_UNENCRYPTED_LOGS_PER_TX: u64 = 8; global NUM_ENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; global NUM_UNENCRYPTED_LOGS_HASHES_PER_TX: u64 = 1; // docs:end:constants +// KERNEL CIRCUIT PRIVATE INPUTS CONSTANTS +global MAX_PUBLIC_DATA_HINTS: u64 = 64; // MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + MAX_PUBLIC_DATA_READS_PER_TX; + // ROLLUP CONTRACT CONSTANTS - constants used only in l1-contracts global NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP: u64 = 16; @@ -96,7 +107,7 @@ global BLOB_SIZE_IN_BYTES: Field = 126976; global NESTED_CALL_L2_GAS_BUFFER = 20000; // CONTRACT CLASS CONSTANTS -global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u64 = 16000; +global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u64 = 16200; // Bytecode size for private functions is per function, not for the entire contract. // Note that private functions bytecode includes a mix of acir and brillig. global MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS: u64 = 3000; @@ -118,7 +129,7 @@ global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af8166354 // CONTRACT INSTANCE CONSTANTS // sha224sum 'struct ContractInstanceDeployed' global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631; -global DEPLOYER_CONTRACT_ADDRESS = 0x2d8e7aedc70b65d49e6aa0794d8d12721896c177e87126701f6e60d184358e74; +global DEPLOYER_CONTRACT_ADDRESS = 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2; // NOIR CONSTANTS - constants used only in yarn-packages/noir-contracts // Some are defined here because Noir doesn't yet support globals referencing other globals yet. @@ -156,13 +167,13 @@ global MAX_BLOCK_NUMBER_LENGTH: u64 = 2; // 1 for the option flag, 1 for the val global NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; global NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; global PARTIAL_STATE_REFERENCE_LENGTH: u64 = 6; -global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = 224; +global PRIVATE_CALL_STACK_ITEM_LENGTH: u64 = 238; // Change this ONLY if you have changed the PrivateCircuitPublicInputs structure. // In other words, if the structure/size of the public inputs of a function call changes then we should change this // constant as well PRIVATE_CALL_STACK_ITEM_LENGTH -global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 221; +global PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 235; // Change this ONLY if you have changed the PublicCircuitPublicInputs structure. -global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 215; +global PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH: u64 = 222; global STATE_REFERENCE_LENGTH: u64 = 8; // 2 for snap + 8 for partial global TX_CONTEXT_DATA_LENGTH: u64 = 4; global TX_REQUEST_LENGTH: u64 = 18; // 2 + TX_CONTEXT_DATA_LENGTH + FUNCTION_DATA_LENGTH + GAS_SETTINGS_LENGTH diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr index 396ed601c2f..8721314a68b 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/hash.nr @@ -3,6 +3,8 @@ use crate::mocked::VerificationKey; use crate::abis::function_selector::FunctionSelector; use crate::abis::contract_class_function_leaf_preimage::ContractClassFunctionLeafPreimage; use crate::contract_class_id::ContractClassId; +use crate::abis::side_effect::SideEffect; +use crate::traits::is_empty; use crate::utils::{uint256::U256, field::field_from_bytes_32_trunc}; use crate::constants::{ FUNCTION_TREE_HEIGHT, GENERATOR_INDEX__SILOED_NOTE_HASH, GENERATOR_INDEX__OUTER_NULLIFIER, @@ -118,13 +120,33 @@ pub fn accumulate_sha256(input: [Field; 2]) -> Field { sha256_to_field(hash_input_flattened) } -pub fn compute_logs_hash(previous_log_hash: Field, current_log_hash: Field) -> Field { - accumulate_sha256( - [ - previous_log_hash, - current_log_hash - ] - ) +pub fn compute_tx_logs_hash(logs: [SideEffect; MAX_ENCRYPTED_LOGS_PER_TX]) -> Field { + // TODO(Miranda): Below is flat hashing which would reduce constraints (we now only hash once in tail) - convert to this? + + // // Convert each field element into a byte array and append the bytes to `hash_input_flattened` + // // Ideally we would define a new global here but for now we assert in case MAX_LOGS changes + // assert(MAX_ENCRYPTED_LOGS_PER_TX * 32 == 256); + // let mut hash_input_flattened = [0; 256]; + // for offset in 0..MAX_ENCRYPTED_LOGS_PER_TX { + // let input_as_bytes = logs[offset].value.to_be_bytes(32); + // for byte_index in 0..32 { + // hash_input_flattened[offset * 32 + byte_index] = input_as_bytes[byte_index]; + // } + // } + // // This differs from accumulate_sha256 as we could increase MAX_LOGS and + // // ideally we would push to a slice then hash, but in practice compilation was very slow + // // Hardcode to 256 bytes for now + // sha256_to_field(hash_input_flattened) + + // Assuming logs are pre-sorted + let mut accumulated_logs_hash = 0; + for i in 0..MAX_ENCRYPTED_LOGS_PER_TX { + if !is_empty(logs[i]) { + accumulated_logs_hash = accumulate_sha256([accumulated_logs_hash, logs[i].value]); + } + } + + accumulated_logs_hash } pub fn compute_note_hash_nonce(first_nullifier: Field, commitment_index: u64) -> Field { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr index 67b23d3f449..9ef29b02628 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree.nr @@ -7,8 +7,8 @@ mod root; use leaf_preimage::{IndexedTreeLeafPreimage, LeafPreimage}; use membership::{ - assert_check_membership, assert_check_non_membership, check_membership, check_non_membership, - MembershipWitness + assert_check_membership, assert_check_non_membership, check_membership, + conditionally_assert_check_membership, MembershipWitness }; use merkle_tree::MerkleTree; use root::{calculate_empty_tree_root, calculate_subtree_root, root_from_sibling_path}; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr index bd8d3d1b482..28d880c9891 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree.nr @@ -1,3 +1,5 @@ +mod check_valid_low_leaf; + use crate::{ abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot}, merkle_tree::{ diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree/check_valid_low_leaf.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree/check_valid_low_leaf.nr new file mode 100644 index 00000000000..01b4136bded --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/indexed_tree/check_valid_low_leaf.nr @@ -0,0 +1,78 @@ +use crate::merkle_tree::leaf_preimage::IndexedTreeLeafPreimage; + +pub fn assert_check_valid_low_leaf( + key: Field, + low_leaf_preimage: LEAF_PREIMAGE +) where LEAF_PREIMAGE: IndexedTreeLeafPreimage { + let low_key = low_leaf_preimage.get_key(); + let next_key = low_leaf_preimage.get_next_key(); + + assert(low_key.lt(key), "Key is not greater than the low leaf"); + assert(key.lt(next_key) | (next_key == 0), "Key is not less than the next leaf"); +} + +mod tests { + use crate::{ + merkle_tree::{ + leaf_preimage::IndexedTreeLeafPreimage, + indexed_tree::check_valid_low_leaf::assert_check_valid_low_leaf + } + }; + + struct TestLeafPreimage { + value: Field, + next_value: Field, + } + + impl IndexedTreeLeafPreimage for TestLeafPreimage { + fn get_key(self) -> Field { + self.value + } + + fn get_next_key(self) -> Field { + self.next_value + } + + fn as_leaf(self) -> Field { + self.value + } + } + + #[test] + fn test_assert_check_valid_low_leaf() { + let key = 12; + let leaf = TestLeafPreimage { value: 11, next_value: 13 }; + assert_check_valid_low_leaf(key, leaf); + } + + #[test] + fn test_assert_check_empty_low_leaf() { + // An all-zero low leaf should be valid. It could be used as the first dummy leaf in a tree. + // It's not possible to prove against an empty leaf at an uninitialized index. + // The membership check will fail because the leaf value hash(0, 0) is not 0. + let key = 12; + let leaf = TestLeafPreimage { value: 0, next_value: 0 }; + assert_check_valid_low_leaf(key, leaf); + } + + #[test(should_fail_with="Key is not greater than the low leaf")] + fn test_assert_check_valid_low_leaf_failed_wrong_low_leaf() { + let key = 12; + let leaf = TestLeafPreimage { value: 13, next_value: 15 }; + assert_check_valid_low_leaf(key, leaf); + } + + #[test(should_fail_with="Key is not greater than the low leaf")] + fn test_assert_check_valid_low_leaf_failed_is_low_leaf() { + let key = 12; + let leaf = TestLeafPreimage { value: 12, next_value: 15 }; + assert_check_valid_low_leaf(key, leaf); + } + + #[test(should_fail_with="Key is not less than the next leaf")] + fn test_assert_check_valid_low_leaf_failed_wrong_next_key() { + let key = 12; + let leaf = TestLeafPreimage { value: 9, next_value: 11 }; + assert_check_valid_low_leaf(key, leaf); + } +} diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr index d7847467dc1..d549f269984 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/merkle_tree/membership.nr @@ -1,4 +1,10 @@ -use crate::{merkle_tree::{leaf_preimage::IndexedTreeLeafPreimage, root::root_from_sibling_path}, traits::Empty}; +use crate::{ + merkle_tree::{ + leaf_preimage::IndexedTreeLeafPreimage, + indexed_tree::check_valid_low_leaf::assert_check_valid_low_leaf, root::root_from_sibling_path +}, + traits::Empty +}; struct MembershipWitness { leaf_index: Field, @@ -19,36 +25,18 @@ pub fn check_membership(leaf: Field, index: Field, sibling_path: [Field; N], calculated_root == root } -pub fn assert_check_membership(leaf: Field, index: Field, sibling_path: [Field; N], root: Field) { +pub fn assert_check_membership(leaf: Field, index: Field, sibling_path: [Field; TREE_HEIGHT], root: Field) { assert(check_membership(leaf, index, sibling_path, root), "membership check failed"); } -struct NonMembershipCheckErrorCodeEnum { - NADA: u64, - IS_EMPTY: u64, - NOT_EXISTS: u64, - NOT_GREATER_THAN_LOW: u64, - NOT_LESS_THAN_NEXT: u64, -} - -global NonMembershipCheckErrorCode = NonMembershipCheckErrorCodeEnum { - NADA: 0, - IS_EMPTY: 1, - NOT_EXISTS: 2, - NOT_GREATER_THAN_LOW: 3, - NOT_LESS_THAN_NEXT: 4, -}; - -fn check_non_membership_internal( +pub fn assert_check_non_membership( key: Field, low_leaf_preimage: LEAF_PREIMAGE, low_leaf_membership_witness: MembershipWitness, tree_root: Field -) -> u64 where +) where LEAF_PREIMAGE: IndexedTreeLeafPreimage { - let low_key = low_leaf_preimage.get_key(); - let next_key = low_leaf_preimage.get_next_key(); - let is_empty_leaf = (low_key == 0) & (next_key == 0); + assert_check_valid_low_leaf(key, low_leaf_preimage); let low_leaf_exists = check_membership( low_leaf_preimage.as_leaf(), @@ -56,52 +44,31 @@ fn check_non_membership_internal( low_leaf_membership_witness.sibling_path, tree_root ); - - if is_empty_leaf { - NonMembershipCheckErrorCode.IS_EMPTY - } else if !low_leaf_exists { - NonMembershipCheckErrorCode.NOT_EXISTS - } else if !low_key.lt(key) { - NonMembershipCheckErrorCode.NOT_GREATER_THAN_LOW - } else if !key.lt(next_key) & (next_key != 0) { - NonMembershipCheckErrorCode.NOT_LESS_THAN_NEXT - } else { - NonMembershipCheckErrorCode.NADA - } + assert(low_leaf_exists, "Low leaf does not exist"); } -pub fn check_non_membership( +// Prove either membership or non-membership depending on the value of `exists`. +// If `exists` == false, `key` is not in the tree, `leaf_preimage` and `membership_witness` are for the low leaf. +pub fn conditionally_assert_check_membership( key: Field, - low_leaf_preimage: LEAF_PREIMAGE, - low_leaf_membership_witness: MembershipWitness, - tree_root: Field -) -> bool where - LEAF_PREIMAGE: IndexedTreeLeafPreimage { - let error = check_non_membership_internal(key, low_leaf_preimage, low_leaf_membership_witness, tree_root); - error == NonMembershipCheckErrorCode.NADA -} - -pub fn assert_check_non_membership( - key: Field, - low_leaf_preimage: LEAF_PREIMAGE, - low_leaf_membership_witness: MembershipWitness, + exists: bool, + leaf_preimage: LEAF_PREIMAGE, + membership_witness: MembershipWitness, tree_root: Field ) where LEAF_PREIMAGE: IndexedTreeLeafPreimage { - let error = check_non_membership_internal(key, low_leaf_preimage, low_leaf_membership_witness, tree_root); - if error != NonMembershipCheckErrorCode.NADA { - assert( - error != NonMembershipCheckErrorCode.IS_EMPTY, "Cannot check non membership against empty leaf" - ); - assert(error != NonMembershipCheckErrorCode.NOT_EXISTS, "Low leaf does not exist"); - assert( - error != NonMembershipCheckErrorCode.NOT_GREATER_THAN_LOW, "Key is not greater than the low leaf" - ); - assert( - error != NonMembershipCheckErrorCode.NOT_LESS_THAN_NEXT, "Key is not less than the next leaf" - ); - assert(false, "Unknown error"); + if exists { + assert(key == leaf_preimage.get_key(), "Key does not match the key of the leaf preimage"); + } else { + assert_check_valid_low_leaf(key, leaf_preimage); } + + assert_check_membership( + leaf_preimage.as_leaf(), + membership_witness.leaf_index, + membership_witness.sibling_path, + tree_root + ); } mod tests { @@ -109,8 +76,8 @@ mod tests { merkle_tree::{ leaf_preimage::{IndexedTreeLeafPreimage, LeafPreimage}, membership::{ - assert_check_membership, assert_check_non_membership, check_membership, check_non_membership, - MembershipWitness + assert_check_membership, assert_check_non_membership, check_membership, + conditionally_assert_check_membership, MembershipWitness } }, tests::merkle_tree_utils::NonEmptyMerkleTree @@ -186,7 +153,7 @@ mod tests { ); } - fn check_non_membership_at_index(low_leaf_index: u64, leaf: Field) -> bool { + fn assert_check_non_membership_at_index(low_leaf_index: u64, key: Field) { let tree = build_tree(); let tree_root = tree.get_root(); let leaf_preimage = if low_leaf_index < leaf_preimages.len() { @@ -195,15 +162,15 @@ mod tests { TestLeafPreimage { value: 0, next_value: 0 } }; - check_non_membership( - leaf, + assert_check_non_membership( + key, leaf_preimage, MembershipWitness { leaf_index: low_leaf_index as Field, sibling_path: tree.get_sibling_path(low_leaf_index) } , tree_root - ) + ); } - fn assert_check_non_membership_at_index(low_leaf_index: u64, leaf: Field) { + fn conditionally_assert_check_membership_at_index(exists: bool, low_leaf_index: u64, key: Field) { let tree = build_tree(); let tree_root = tree.get_root(); let leaf_preimage = if low_leaf_index < leaf_preimages.len() { @@ -212,8 +179,9 @@ mod tests { TestLeafPreimage { value: 0, next_value: 0 } }; - assert_check_non_membership( - leaf, + conditionally_assert_check_membership( + key, + exists, leaf_preimage, MembershipWitness { leaf_index: low_leaf_index as Field, sibling_path: tree.get_sibling_path(low_leaf_index) } , tree_root @@ -270,80 +238,89 @@ mod tests { ); } - #[test] - fn test_check_non_membership() { - assert_eq(check_non_membership_at_index(0, 25), true); - } - #[test] fn test_assert_check_non_membership() { assert_check_non_membership_at_index(0, 25); } - #[test] - fn test_check_non_membership_greater_than_max() { - assert_eq(check_non_membership_at_index(1, 45), true); - } - #[test] fn test_assert_check_non_membership_greater_than_max() { assert_check_non_membership_at_index(1, 45); } - #[test] - fn test_check_non_membership_false_empty_leaf() { - assert_eq(check_non_membership_at_index(4, 25), false); + #[test(should_fail_with="Key is not greater than the low leaf")] + fn test_assert_check_non_membership_failed_wrong_low_leaf() { + assert_check_non_membership_at_index(3, 25); } - #[test(should_fail_with="Cannot check non membership against empty leaf")] - fn test_assert_check_non_membership_failed_empty_leaf() { - assert_check_non_membership_at_index(4, 25); + #[test(should_fail_with="Key is not less than the next leaf")] + fn test_assert_check_non_membership_failed_wrong_next_key() { + assert_check_non_membership_at_index(2, 25); } - #[test] - fn test_check_non_membership_false_wrong_low_leaf() { - assert_eq(check_non_membership_at_index(3, 25), false); + #[test(should_fail_with="Low leaf does not exist")] + fn test_assert_check_non_membership_failed_invalid_leaf() { + let tree = build_tree(); + let tree_root = tree.get_root(); + + let fake_leaf = TestLeafPreimage { value: 50, next_value: 60 }; + assert_check_non_membership( + 55, + fake_leaf, + MembershipWitness { leaf_index: 1, sibling_path: tree.get_sibling_path(1) } , + tree_root + ); } - #[test(should_fail_with="Key is not greater than the low leaf")] - fn test_assert_check_non_membership_failed_wrong_low_leaf() { - assert_check_non_membership_at_index(3, 25); + #[test] + fn test_conditionally_assert_check_membership_exists() { + conditionally_assert_check_membership_at_index(true, 1, leaf_preimages[1].get_key()); } #[test] - fn test_check_non_membership_false_wrong_next_key() { - assert_eq(check_non_membership_at_index(2, 25), false); + fn test_conditionally_assert_check_membership_not_exists() { + conditionally_assert_check_membership_at_index(false, 1, leaf_preimages[1].get_key() + 1); + } + + #[test(should_fail_with="Key does not match the key of the leaf preimage")] + fn test_conditionally_assert_check_membership_exists_value_mismatch() { + conditionally_assert_check_membership_at_index(true, 1, leaf_preimages[1].get_key() + 1); + } + + #[test(should_fail_with="Key is not greater than the low leaf")] + fn test_conditionally_assert_check_membership_failed_not_exists_wrong_low_leaf() { + conditionally_assert_check_membership_at_index(false, 3, 25); } #[test(should_fail_with="Key is not less than the next leaf")] - fn test_assert_check_non_membership_failed_wrong_next_key() { - assert_check_non_membership_at_index(2, 25); + fn test_conditionally_assert_check_membership_failed_not_exists_wrong_next_key() { + conditionally_assert_check_membership_at_index(false, 2, 25); } - #[test] - fn test_check_non_membership_false_invalid_leaf() { + #[test(should_fail_with="membership check failed")] + fn test_conditionally_assert_check_membership_failed_exists_invalid_leaf() { let tree = build_tree(); let tree_root = tree.get_root(); - let fake_leaf = TestLeafPreimage { value: 50, next_value: 60 }; - assert_eq( - check_non_membership( - 55, - fake_leaf, - MembershipWitness { leaf_index: 1, sibling_path: tree.get_sibling_path(1) } , - tree_root - ), false + let exists = true; + conditionally_assert_check_membership( + 50, + exists, + fake_leaf, + MembershipWitness { leaf_index: 1, sibling_path: tree.get_sibling_path(1) } , + tree_root ); } - #[test(should_fail_with="Low leaf does not exist")] - fn test_assert_check_non_membership_failed_invalid_leaf() { + #[test(should_fail_with="membership check failed")] + fn test_conditionally_assert_check_membership_failed_not_exists_invalid_leaf() { let tree = build_tree(); let tree_root = tree.get_root(); - let fake_leaf = TestLeafPreimage { value: 50, next_value: 60 }; - assert_check_non_membership( + let exists = false; + conditionally_assert_check_membership( 55, + exists, fake_leaf, MembershipWitness { leaf_index: 1, sibling_path: tree.get_sibling_path(1) } , tree_root diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr b/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr index dcc84fe7026..992bbdecd18 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/public_data_tree_leaf_preimage.nr @@ -1,4 +1,4 @@ -use crate::traits::{Empty, Hash}; +use crate::{merkle_tree::leaf_preimage::IndexedTreeLeafPreimage, traits::{Empty, Hash}}; struct PublicDataTreeLeafPreimage { slot : Field, @@ -28,6 +28,20 @@ impl Hash for PublicDataTreeLeafPreimage { } } +impl IndexedTreeLeafPreimage for PublicDataTreeLeafPreimage { + fn get_key(self) -> Field { + self.slot + } + + fn get_next_key(self) -> Field { + self.next_slot + } + + fn as_leaf(self) -> Field { + self.hash() + } +} + impl PublicDataTreeLeafPreimage { pub fn is_empty(self) -> bool { (self.slot == 0) & (self.value == 0) & (self.next_slot == 0) & (self.next_index == 0) diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr index 9c6a861edde..d0e54861371 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/fixture_builder.nr @@ -21,10 +21,11 @@ use crate::{ MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_READ_REQUESTS_PER_TX, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, - VK_TREE_HEIGHT + VK_TREE_HEIGHT, MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX }, hash::silo_nullifier, header::Header, mocked::{AggregationObject, Proof, VerificationKey}, - tests::fixtures, transaction::tx_context::TxContext, traits::Empty + partial_state_reference::PartialStateReference, tests::fixtures, transaction::tx_context::TxContext, + traits::Empty }; struct FixtureBuilder { @@ -40,6 +41,8 @@ struct FixtureBuilder { new_note_hashes: BoundedVec, new_nullifiers: BoundedVec, new_l2_to_l1_msgs: BoundedVec, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, encrypted_logs_hash: Field, unencrypted_logs_hash: Field, encrypted_log_preimages_length: Field, @@ -67,6 +70,9 @@ struct FixtureBuilder { // Counters. min_revertible_side_effect_counter: u32, counter: u32, + + // States. + start_state: PartialStateReference, } impl FixtureBuilder { @@ -81,6 +87,8 @@ impl FixtureBuilder { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), + encrypted_logs_hashes: BoundedVec::new(), + unencrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hash: 0, unencrypted_logs_hash: 0, encrypted_log_preimages_length: 0, @@ -101,6 +109,7 @@ impl FixtureBuilder { revert_code: 0, min_revertible_side_effect_counter: 0, counter: 0, + start_state: PartialStateReference::empty(), gas_used: Gas::empty(), gas_settings: GasSettings::empty() } @@ -119,8 +128,8 @@ impl FixtureBuilder { new_note_hashes: self.new_note_hashes, new_nullifiers: self.new_nullifiers, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs, - encrypted_logs_hash: self.encrypted_logs_hash, - unencrypted_logs_hash: self.unencrypted_logs_hash, + encrypted_logs_hashes: self.encrypted_logs_hashes, + unencrypted_logs_hashes: self.unencrypted_logs_hashes, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, private_call_stack: self.private_call_stack, @@ -135,8 +144,8 @@ impl FixtureBuilder { new_note_hashes: self.new_note_hashes, new_nullifiers: self.new_nullifiers, new_l2_to_l1_msgs: self.new_l2_to_l1_msgs, - encrypted_logs_hash: self.encrypted_logs_hash, - unencrypted_logs_hash: self.unencrypted_logs_hash, + encrypted_logs_hashes: self.encrypted_logs_hashes, + unencrypted_logs_hashes: self.unencrypted_logs_hashes, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, public_data_update_requests: self.public_data_update_requests, @@ -231,6 +240,7 @@ impl FixtureBuilder { rollup_validation_requests, end, constants, + start_state: self.start_state, revert_code: self.revert_code } } @@ -267,17 +277,21 @@ impl FixtureBuilder { } } + pub fn add_public_data_update_request(&mut self, leaf_slot: Field, value: Field) { + let update_request = PublicDataUpdateRequest { leaf_slot, new_value: value }; + self.public_data_update_requests.push(update_request); + } + pub fn append_public_data_update_requests(&mut self, num_updates: u64) { let value_offset = self.public_data_update_requests.len(); for i in 0..MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX { if i < num_updates { - let update_request = PublicDataUpdateRequest { - // The default leaf index is its index + 23. - leaf_slot: (value_offset + i + 23) as Field, - // The default value is its index + 678. - new_value: (value_offset + i + 678) as Field - }; - self.public_data_update_requests.push(update_request); + // The default leaf index is its index + 23. + // The default value is its index + 678. + self.add_public_data_update_request( + (value_offset + i + 23) as Field, + (value_offset + i + 678) as Field + ); } } } @@ -326,12 +340,32 @@ impl FixtureBuilder { self.nullifier_non_existent_read_requests.push(read_request); } + pub fn add_read_request_for_pending_public_data(&mut self, public_date_update_request_index: u64) -> u64 { + let new_read_request_index = self.public_data_reads.len(); + let public_write = self.public_data_update_requests.get(public_date_update_request_index); + let read_request = PublicDataRead { leaf_slot: public_write.leaf_slot, value: public_write.new_value }; + self.public_data_reads.push(read_request); + new_read_request_index + } + pub fn set_encrypted_logs(&mut self, hash: Field, preimages_length: Field) { + let side_effect = SideEffect { value: hash, counter: self.next_counter() }; + self.encrypted_logs_hashes.push(side_effect); + self.encrypted_log_preimages_length += preimages_length; + } + + pub fn set_unencrypted_logs(&mut self, hash: Field, preimages_length: Field) { + let side_effect = SideEffect { value: hash, counter: self.next_counter() }; + self.unencrypted_logs_hashes.push(side_effect); + self.unencrypted_log_preimages_length += preimages_length; + } + + pub fn set_encrypted_logs_hash(&mut self, hash: Field, preimages_length: Field) { self.encrypted_logs_hash = hash; self.encrypted_log_preimages_length = preimages_length; } - pub fn set_unencrypted_logs(&mut self, hash: Field, preimages_length: Field) { + pub fn set_unencrypted_logs_hash(&mut self, hash: Field, preimages_length: Field) { self.unencrypted_logs_hash = hash; self.unencrypted_log_preimages_length = preimages_length; } @@ -399,6 +433,8 @@ impl Empty for FixtureBuilder { new_note_hashes: BoundedVec::new(), new_nullifiers: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), + encrypted_logs_hashes: BoundedVec::new(), + unencrypted_logs_hashes: BoundedVec::new(), encrypted_logs_hash: 0, unencrypted_logs_hash: 0, encrypted_log_preimages_length: 0, @@ -419,6 +455,7 @@ impl Empty for FixtureBuilder { revert_code: 0, min_revertible_side_effect_counter: 0, counter: 0, + start_state: PartialStateReference::empty(), gas_settings: GasSettings::empty(), gas_used: Gas::empty(), } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr index 6063bef7866..bceb7f0fbba 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_call_data_builder.nr @@ -4,8 +4,8 @@ use crate::{ private_call_stack_item::PrivateCallStackItem, function_data::FunctionData, max_block_number::MaxBlockNumber, membership_witness::{FunctionLeafMembershipWitness, NoteHashReadRequestMembershipWitness}, - private_circuit_public_inputs::PrivateCircuitPublicInputs, - private_kernel::private_call_data::PrivateCallData + private_circuit_public_inputs::{PrivateCircuitPublicInputs}, + private_kernel::private_call_data::PrivateCallData, side_effect::SideEffect, }, address::{AztecAddress, EthAddress, SaltedInitializationHash, PublicKeysHash}, mocked::{Proof, VerificationKey}, @@ -160,13 +160,17 @@ impl PrivateCallDataBuilder { } pub fn set_encrypted_logs(&mut self, hash: Field, preimages_length: Field) { - self.public_inputs.encrypted_logs_hash = hash; - self.public_inputs.encrypted_log_preimages_length = preimages_length; + // Counter set as 0 for testing, like note read requests + let side_effect = SideEffect { value: hash, counter: 0 }; + self.public_inputs.encrypted_logs_hashes.push(side_effect); + self.public_inputs.encrypted_log_preimages_length += preimages_length; } pub fn set_unencrypted_logs(&mut self, hash: Field, preimages_length: Field) { - self.public_inputs.unencrypted_logs_hash = hash; - self.public_inputs.unencrypted_log_preimages_length = preimages_length; + // Counter set as 0 for testing, like note read requests + let side_effect = SideEffect { value: hash, counter: 0 }; + self.public_inputs.unencrypted_logs_hashes.push(side_effect); + self.public_inputs.unencrypted_log_preimages_length += preimages_length; } pub fn get_call_stack_item_hash(self) -> Field { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr index 5858a61e8a2..e72d8ee686e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/private_circuit_public_inputs_builder.nr @@ -13,8 +13,9 @@ use crate::{ MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, - MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL -}, + MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, + MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL + }, traits::Empty }; @@ -39,8 +40,8 @@ struct PrivateCircuitPublicInputsBuilder { public_call_stack_hashes: BoundedVec, new_l2_to_l1_msgs: BoundedVec, - encrypted_logs_hash: Field, - unencrypted_logs_hash: Field, + encrypted_logs_hashes: BoundedVec, + unencrypted_logs_hashes: BoundedVec, encrypted_log_preimages_length: Field, unencrypted_log_preimages_length: Field, @@ -103,8 +104,8 @@ impl PrivateCircuitPublicInputsBuilder { new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, start_side_effect_counter: self.call_context.side_effect_counter, end_side_effect_counter: 10, - encrypted_logs_hash: self.encrypted_logs_hash, - unencrypted_logs_hash: self.unencrypted_logs_hash, + encrypted_logs_hashes: self.encrypted_logs_hashes.storage, + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, encrypted_log_preimages_length: self.encrypted_log_preimages_length, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, historical_header: self.historical_header, @@ -130,8 +131,8 @@ impl Empty for PrivateCircuitPublicInputsBuilder { private_call_stack_hashes: BoundedVec::new(), public_call_stack_hashes: BoundedVec::new(), new_l2_to_l1_msgs: BoundedVec::new(), - encrypted_logs_hash: 0, - unencrypted_logs_hash: 0, + encrypted_logs_hashes: BoundedVec::new(), + unencrypted_logs_hashes: BoundedVec::new(), encrypted_log_preimages_length: 0, unencrypted_log_preimages_length: 0, historical_header: Header::empty(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr index 5efc84e71df..262a2dd4c54 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_call_data_builder.nr @@ -3,7 +3,7 @@ use crate::{ gas_settings::GasSettings, gas::Gas, call_context::CallContext, call_request::{CallerContext, CallRequest}, function_data::FunctionData, public_call_data::PublicCallData, public_call_stack_item::PublicCallStackItem, - public_circuit_public_inputs::PublicCircuitPublicInputs + public_circuit_public_inputs::PublicCircuitPublicInputs, side_effect::SideEffect }, address::{AztecAddress, EthAddress}, contrakt::{storage_read::StorageRead, storage_update_request::StorageUpdateRequest}, mocked::Proof, @@ -152,8 +152,10 @@ impl PublicCallDataBuilder { } pub fn set_unencrypted_logs(&mut self, hash: Field, preimages_length: Field) { - self.public_inputs.unencrypted_logs_hash = hash; - self.public_inputs.unencrypted_log_preimages_length = preimages_length; + // Counter set as 0 for testing, like note read requests + let side_effect = SideEffect { value: hash, counter: 0 }; + self.public_inputs.unencrypted_logs_hashes.push(side_effect); + self.public_inputs.unencrypted_log_preimages_length += preimages_length; } pub fn finish(self) -> PublicCallData { diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr index c719774093e..6556b96d8ac 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/tests/public_circuit_public_inputs_builder.nr @@ -12,7 +12,7 @@ use crate::{ MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL }, traits::Empty }; @@ -31,7 +31,7 @@ struct PublicCircuitPublicInputsBuilder { new_l2_to_l1_msgs: BoundedVec, start_side_effect_counter: u32, end_side_effect_counter: u32, - unencrypted_logs_hash: Field, + unencrypted_logs_hashes: BoundedVec, unencrypted_log_preimages_length: Field, historical_header: Header, prover_address: AztecAddress, @@ -62,7 +62,7 @@ impl PublicCircuitPublicInputsBuilder { new_l2_to_l1_msgs: self.new_l2_to_l1_msgs.storage, start_side_effect_counter: self.start_side_effect_counter, end_side_effect_counter: self.end_side_effect_counter, - unencrypted_logs_hash: self.unencrypted_logs_hash, + unencrypted_logs_hashes: self.unencrypted_logs_hashes.storage, unencrypted_log_preimages_length: self.unencrypted_log_preimages_length, historical_header: self.historical_header, prover_address: self.prover_address, @@ -88,7 +88,7 @@ impl Empty for PublicCircuitPublicInputsBuilder { new_l2_to_l1_msgs: BoundedVec::new(), start_side_effect_counter: 0 as u32, end_side_effect_counter: 0 as u32, - unencrypted_logs_hash: 0, + unencrypted_logs_hashes: BoundedVec::new(), unencrypted_log_preimages_length: 0, historical_header: Header::empty(), prover_address: AztecAddress::zero(), diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr b/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr index 70870f64d84..4d272c90cba 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/traits.nr @@ -1,4 +1,5 @@ use dep::std::cmp::Eq; +use crate::utils::field::field_from_bytes; // Trait: is_empty // @@ -55,6 +56,12 @@ impl ToField for U128 { self.to_integer() } } +impl ToField for str { + fn to_field(self) -> Field { + assert(N < 32, "String doesn't fit in a field, consider using Serialize instead"); + field_from_bytes(self.as_bytes(), true) + } +} trait FromField { fn from_field(value: Field) -> Self; @@ -83,6 +90,17 @@ trait Serialize { } // docs:end:serialize +impl Serialize for str { + fn serialize(self) -> [Field; N] { + let mut result = [0; N]; + let bytes: [u8; N] = self.as_bytes(); + for i in 0..N { + result[i] = field_from_bytes([bytes[i];1], true); + } + result + } +} + // docs:start:deserialize trait Deserialize { fn deserialize(fields: [Field; N]) -> Self; diff --git a/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml b/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml index 0b2855fa834..cdd7a064a8d 100644 --- a/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml +++ b/noir/noir-repo/.github/workflows/test-rust-workspace-msrv.yml @@ -112,6 +112,10 @@ jobs: # We treat any cancelled, skipped or failing jobs as a failure for the workflow as a whole. FAIL: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }} + - name: Checkout + if: ${{ failure() }} + uses: actions/checkout@v4 + # Raise an issue if the tests failed - name: Alert on failed publish uses: JasonEtco/create-an-issue@v2 @@ -122,4 +126,4 @@ jobs: WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} with: update_existing: true - filename: .github/JS_PUBLISH_FAILED.md \ No newline at end of file + filename: .github/ACVM_NOT_PUBLISHABLE.md diff --git a/noir/noir-repo/.gitignore b/noir/noir-repo/.gitignore index 9a829afab8b..2c877a4d02c 100644 --- a/noir/noir-repo/.gitignore +++ b/noir/noir-repo/.gitignore @@ -4,6 +4,7 @@ examples/**/target/ examples/9 node_modules pkg/ +.idea # Yarn .pnp.* diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index ee7d1d7d024..ee83f7f8ddf 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -61,6 +61,7 @@ dependencies = [ "blake3", "k256", "keccak", + "num-bigint", "p256", "sha2", "sha3", @@ -269,7 +270,7 @@ dependencies = [ "ark-std", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -286,7 +287,7 @@ dependencies = [ "ark-std", "derivative", "digest", - "itertools", + "itertools 0.10.5", "num-bigint", "num-traits", "paste", @@ -375,6 +376,15 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "assert_cmd" version = "2.0.12" @@ -607,11 +617,14 @@ dependencies = [ "ark-ec", "ark-ff", "cfg-if 1.0.0", + "criterion", "getrandom 0.2.10", + "hex", "js-sys", + "lazy_static", "noir_grumpkin", "num-bigint", - "num-traits", + "pprof", "thiserror", "wasm-bindgen-futures", "wasmer", @@ -1179,7 +1192,7 @@ dependencies = [ "clap", "criterion-plot", "is-terminal", - "itertools", + "itertools 0.10.5", "num-traits", "once_cell", "oorandom", @@ -1200,7 +1213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] @@ -1256,6 +1269,12 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-bigint" version = "0.4.9" @@ -1527,6 +1546,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ena" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +dependencies = [ + "log", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -2365,6 +2393,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" @@ -2535,6 +2572,37 @@ dependencies = [ "libc", ] +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set", + "ena", + "itertools 0.11.0", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax 0.8.2", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata 0.4.5", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -2857,6 +2925,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nibble_vec" version = "0.1.0" @@ -3088,6 +3162,8 @@ dependencies = [ "chumsky", "fm", "iter-extended", + "lalrpop", + "lalrpop-util", "noirc_errors", "noirc_printable_type", "petgraph", @@ -3387,6 +3463,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3471,6 +3553,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "predicates" version = "2.1.5" @@ -3479,7 +3567,7 @@ checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" dependencies = [ "difflib", "float-cmp", - "itertools", + "itertools 0.10.5", "normalize-line-endings", "predicates-core", "regex", @@ -3493,7 +3581,7 @@ checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" dependencies = [ "anstyle", "difflib", - "itertools", + "itertools 0.10.5", "predicates-core", ] @@ -4613,6 +4701,19 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot 0.12.1", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "strsim" version = "0.10.0" @@ -4855,6 +4956,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -5276,9 +5386,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs index 0c79cfdb815..d655d136bc8 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/mod.rs @@ -89,6 +89,16 @@ impl Circuit { } } +#[derive(Debug, Copy, Clone)] +/// The opcode location for a call to a separate ACIR circuit +/// This includes the function index of the caller within a [program][Program] +/// and the index in the callers ACIR to the specific call opcode. +/// This is only resolved and set during circuit execution. +pub struct ResolvedOpcodeLocation { + pub acir_function_index: usize, + pub opcode_location: OpcodeLocation, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] /// Opcodes are locatable so that callers can /// map opcodes to debug information related to their context. @@ -266,6 +276,10 @@ impl std::fmt::Display for Program { writeln!(f, "func {}", func_index)?; writeln!(f, "{}", function)?; } + for (func_index, function) in self.unconstrained_functions.iter().enumerate() { + writeln!(f, "unconstrained func {}", func_index)?; + writeln!(f, "{:?}", function.bytecode)?; + } Ok(()) } } diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/blackbox/bigint.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/blackbox/bigint.rs index f094bb1ba20..3c05fb2761d 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/blackbox/bigint.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/blackbox/bigint.rs @@ -1,53 +1,23 @@ -use std::collections::HashMap; - use acir::{ circuit::opcodes::FunctionInput, native_types::{Witness, WitnessMap}, BlackBoxFunc, FieldElement, }; -use num_bigint::BigUint; +use acvm_blackbox_solver::BigIntSolver; use crate::pwg::OpcodeResolutionError; -/// Resolve BigInt opcodes by storing BigInt values (and their moduli) by their ID in a HashMap: +/// Resolve BigInt opcodes by storing BigInt values (and their moduli) by their ID in the BigIntSolver /// - When it encounters a bigint operation opcode, it performs the operation on the stored values /// and store the result using the provided ID. /// - When it gets a to_bytes opcode, it simply looks up the value and resolves the output witness accordingly. #[derive(Default)] -pub(crate) struct BigIntSolver { - bigint_id_to_value: HashMap, - bigint_id_to_modulus: HashMap, +pub(crate) struct AcvmBigIntSolver { + bigint_solver: BigIntSolver, } -impl BigIntSolver { - pub(crate) fn get_bigint( - &self, - id: u32, - func: BlackBoxFunc, - ) -> Result { - self.bigint_id_to_value - .get(&id) - .ok_or(OpcodeResolutionError::BlackBoxFunctionFailed( - func, - format!("could not find bigint of id {id}"), - )) - .cloned() - } - - pub(crate) fn get_modulus( - &self, - id: u32, - func: BlackBoxFunc, - ) -> Result { - self.bigint_id_to_modulus - .get(&id) - .ok_or(OpcodeResolutionError::BlackBoxFunctionFailed( - func, - format!("could not find bigint of id {id}"), - )) - .cloned() - } +impl AcvmBigIntSolver { pub(crate) fn bigint_from_bytes( &mut self, inputs: &[FunctionInput], @@ -59,10 +29,7 @@ impl BigIntSolver { .iter() .map(|input| initial_witness.get(&input.witness).unwrap().to_u128() as u8) .collect::>(); - let bigint = BigUint::from_bytes_le(&bytes); - self.bigint_id_to_value.insert(output, bigint); - let modulus = BigUint::from_bytes_le(modulus); - self.bigint_id_to_modulus.insert(output, modulus); + self.bigint_solver.bigint_from_bytes(&bytes, modulus, output)?; Ok(()) } @@ -72,9 +39,7 @@ impl BigIntSolver { outputs: &[Witness], initial_witness: &mut WitnessMap, ) -> Result<(), OpcodeResolutionError> { - let bigint = self.get_bigint(input, BlackBoxFunc::BigIntToLeBytes)?; - - let mut bytes = bigint.to_bytes_le(); + let mut bytes = self.bigint_solver.bigint_to_bytes(input)?; while bytes.len() < outputs.len() { bytes.push(0); } @@ -91,30 +56,7 @@ impl BigIntSolver { output: u32, func: BlackBoxFunc, ) -> Result<(), OpcodeResolutionError> { - let modulus = self.get_modulus(lhs, func)?; - let lhs = self.get_bigint(lhs, func)?; - let rhs = self.get_bigint(rhs, func)?; - let mut result = match func { - BlackBoxFunc::BigIntAdd => lhs + rhs, - BlackBoxFunc::BigIntSub => { - if lhs >= rhs { - &lhs - &rhs - } else { - &lhs + &modulus - &rhs - } - } - BlackBoxFunc::BigIntMul => lhs * rhs, - BlackBoxFunc::BigIntDiv => { - lhs * rhs.modpow(&(&modulus - BigUint::from(1_u32)), &modulus) - } //TODO ensure that modulus is prime - _ => unreachable!("ICE - bigint_op must be called for an operation"), - }; - if result > modulus { - let q = &result / &modulus; - result -= q * &modulus; - } - self.bigint_id_to_value.insert(output, result); - self.bigint_id_to_modulus.insert(output, modulus); + self.bigint_solver.bigint_op(lhs, rhs, output, func)?; Ok(()) } } diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/blackbox/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/blackbox/mod.rs index 26d1a3c8f86..2753c7baaaa 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/blackbox/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/blackbox/mod.rs @@ -6,7 +6,7 @@ use acir::{ use acvm_blackbox_solver::{blake2s, blake3, keccak256, keccakf1600, sha256}; use self::{ - bigint::BigIntSolver, hash::solve_poseidon2_permutation_opcode, pedersen::pedersen_hash, + bigint::AcvmBigIntSolver, hash::solve_poseidon2_permutation_opcode, pedersen::pedersen_hash, }; use super::{insert_value, OpcodeNotSolvable, OpcodeResolutionError}; @@ -56,7 +56,7 @@ pub(crate) fn solve( backend: &impl BlackBoxFunctionSolver, initial_witness: &mut WitnessMap, bb_func: &BlackBoxFuncCall, - bigint_solver: &mut BigIntSolver, + bigint_solver: &mut AcvmBigIntSolver, ) -> Result<(), OpcodeResolutionError> { let inputs = bb_func.get_inputs_vec(); if !contains_all_inputs(initial_witness, &inputs) { diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs index 9982fa890c2..67faf7f5007 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/brillig.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use acir::{ - brillig::{ForeignCallParam, ForeignCallResult}, + brillig::{ForeignCallParam, ForeignCallResult, Opcode as BrilligOpcode}, circuit::{ brillig::{Brillig, BrilligInputs, BrilligOutputs}, opcodes::BlockId, @@ -46,9 +46,9 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { /// Assigns the zero value to all outputs of the given [`Brillig`] bytecode. pub(super) fn zero_out_brillig_outputs( initial_witness: &mut WitnessMap, - brillig: &Brillig, + outputs: &[BrilligOutputs], ) -> Result<(), OpcodeResolutionError> { - for output in &brillig.outputs { + for output in outputs { match output { BrilligOutputs::Simple(witness) => { insert_value(witness, FieldElement::zero(), initial_witness)?; @@ -63,6 +63,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { Ok(()) } + // TODO: Delete this old method once `Brillig` is deleted /// Constructs a solver for a Brillig block given the bytecode and initial /// witness. pub(crate) fn new( @@ -72,13 +73,45 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { bb_solver: &'b B, acir_index: usize, ) -> Result { + let vm = Self::setup_brillig_vm( + initial_witness, + memory, + &brillig.inputs, + &brillig.bytecode, + bb_solver, + )?; + Ok(Self { vm, acir_index }) + } + + /// Constructs a solver for a Brillig block given the bytecode and initial + /// witness. + pub(crate) fn new_call( + initial_witness: &WitnessMap, + memory: &HashMap, + inputs: &'b [BrilligInputs], + brillig_bytecode: &'b [BrilligOpcode], + bb_solver: &'b B, + acir_index: usize, + ) -> Result { + let vm = + Self::setup_brillig_vm(initial_witness, memory, inputs, brillig_bytecode, bb_solver)?; + Ok(Self { vm, acir_index }) + } + + fn setup_brillig_vm( + initial_witness: &WitnessMap, + memory: &HashMap, + inputs: &[BrilligInputs], + brillig_bytecode: &'b [BrilligOpcode], + bb_solver: &'b B, + ) -> Result, OpcodeResolutionError> { // Set input values let mut calldata: Vec = Vec::new(); // Each input represents an expression or array of expressions to evaluate. // Iterate over each input and evaluate the expression(s) associated with it. // Push the results into memory. // If a certain expression is not solvable, we stall the ACVM and do not proceed with Brillig VM execution. - for input in &brillig.inputs { + for input in inputs { match input { BrilligInputs::Single(expr) => match get_value(expr, initial_witness) { Ok(value) => calldata.push(value), @@ -118,8 +151,8 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { // Instantiate a Brillig VM given the solved calldata // along with the Brillig bytecode. - let vm = VM::new(calldata, &brillig.bytecode, vec![], bb_solver); - Ok(Self { vm, acir_index }) + let vm = VM::new(calldata, brillig_bytecode, vec![], bb_solver); + Ok(vm) } pub fn get_memory(&self) -> &[MemoryValue] { @@ -204,13 +237,13 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { pub(crate) fn finalize( self, witness: &mut WitnessMap, - brillig: &Brillig, + outputs: &[BrilligOutputs], ) -> Result<(), OpcodeResolutionError> { // Finish the Brillig execution by writing the outputs to the witness map let vm_status = self.vm.get_status(); match vm_status { VMStatus::Finished { return_data_offset, return_data_size } => { - self.write_brillig_outputs(witness, return_data_offset, return_data_size, brillig)?; + self.write_brillig_outputs(witness, return_data_offset, return_data_size, outputs)?; Ok(()) } _ => panic!("Brillig VM has not completed execution"), @@ -222,12 +255,12 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { witness_map: &mut WitnessMap, return_data_offset: usize, return_data_size: usize, - brillig: &Brillig, + outputs: &[BrilligOutputs], ) -> Result<(), OpcodeResolutionError> { // Write VM execution results into the witness map let memory = self.vm.get_memory(); let mut current_ret_data_idx = return_data_offset; - for output in brillig.outputs.iter() { + for output in outputs.iter() { match output { BrilligOutputs::Simple(witness) => { insert_value(witness, memory[current_ret_data_idx].to_field(), witness_map)?; @@ -242,6 +275,7 @@ impl<'b, B: BlackBoxFunctionSolver> BrilligSolver<'b, B> { } } } + assert!( current_ret_data_idx == return_data_offset + return_data_size, "Brillig VM did not write the expected number of return values" diff --git a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs index e7c009f87fa..652e173867a 100644 --- a/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs +++ b/noir/noir-repo/acvm-repo/acvm/src/pwg/mod.rs @@ -4,14 +4,14 @@ use std::collections::HashMap; use acir::{ brillig::ForeignCallResult, - circuit::{opcodes::BlockId, Opcode, OpcodeLocation}, + circuit::{brillig::BrilligBytecode, opcodes::BlockId, Opcode, OpcodeLocation}, native_types::{Expression, Witness, WitnessMap}, BlackBoxFunc, FieldElement, }; use acvm_blackbox_solver::BlackBoxResolutionError; use self::{ - arithmetic::ExpressionSolver, blackbox::bigint::BigIntSolver, directives::solve_directives, + arithmetic::ExpressionSolver, blackbox::bigint::AcvmBigIntSolver, directives::solve_directives, memory_op::MemoryOpSolver, }; use crate::BlackBoxFunctionSolver; @@ -148,7 +148,7 @@ pub struct ACVM<'a, B: BlackBoxFunctionSolver> { /// Stores the solver for memory operations acting on blocks of memory disambiguated by [block][`BlockId`]. block_solvers: HashMap, - bigint_solver: BigIntSolver, + bigint_solver: AcvmBigIntSolver, /// A list of opcodes which are to be executed by the ACVM. opcodes: &'a [Opcode], @@ -165,22 +165,31 @@ pub struct ACVM<'a, B: BlackBoxFunctionSolver> { /// Represents the outputs of all ACIR calls during an ACVM process /// List is appended onto by the caller upon reaching a [ACVMStatus::RequiresAcirCall] acir_call_results: Vec>, + + // Each unconstrained function referenced in the program + unconstrained_functions: &'a [BrilligBytecode], } impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { - pub fn new(backend: &'a B, opcodes: &'a [Opcode], initial_witness: WitnessMap) -> Self { + pub fn new( + backend: &'a B, + opcodes: &'a [Opcode], + initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], + ) -> Self { let status = if opcodes.is_empty() { ACVMStatus::Solved } else { ACVMStatus::InProgress }; ACVM { status, backend, block_solvers: HashMap::default(), - bigint_solver: BigIntSolver::default(), + bigint_solver: AcvmBigIntSolver::default(), opcodes, instruction_pointer: 0, witness_map: initial_witness, brillig_solver: None, acir_call_counter: 0, acir_call_results: Vec::default(), + unconstrained_functions, } } @@ -324,9 +333,10 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), res => res.map(|_| ()), }, - Opcode::BrilligCall { .. } => { - todo!("implement brillig pointer handling"); - } + Opcode::BrilligCall { .. } => match self.solve_brillig_call_opcode() { + Ok(Some(foreign_call)) => return self.wait_for_foreign_call(foreign_call), + res => res.map(|_| ()), + }, Opcode::Call { .. } => match self.solve_call_opcode() { Ok(Some(input_values)) => return self.wait_for_acir_call(input_values), res => res.map(|_| ()), @@ -381,7 +391,8 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { let witness = &mut self.witness_map; if is_predicate_false(witness, &brillig.predicate)? { - return BrilligSolver::::zero_out_brillig_outputs(witness, brillig).map(|_| None); + return BrilligSolver::::zero_out_brillig_outputs(witness, &brillig.outputs) + .map(|_| None); } // If we're resuming execution after resolving a foreign call then @@ -407,7 +418,51 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { } BrilligSolverStatus::Finished => { // Write execution outputs - solver.finalize(witness, brillig)?; + solver.finalize(witness, &brillig.outputs)?; + Ok(None) + } + } + } + + fn solve_brillig_call_opcode( + &mut self, + ) -> Result, OpcodeResolutionError> { + let Opcode::BrilligCall { id, inputs, outputs, predicate } = + &self.opcodes[self.instruction_pointer] + else { + unreachable!("Not executing a Brillig opcode"); + }; + + let witness = &mut self.witness_map; + if is_predicate_false(witness, predicate)? { + return BrilligSolver::::zero_out_brillig_outputs(witness, outputs).map(|_| None); + } + + // If we're resuming execution after resolving a foreign call then + // there will be a cached `BrilligSolver` to avoid recomputation. + let mut solver: BrilligSolver<'_, B> = match self.brillig_solver.take() { + Some(solver) => solver, + None => BrilligSolver::new_call( + witness, + &self.block_solvers, + inputs, + &self.unconstrained_functions[*id as usize].bytecode, + self.backend, + self.instruction_pointer, + )?, + }; + match solver.solve()? { + BrilligSolverStatus::ForeignCallWait(foreign_call) => { + // Cache the current state of the solver + self.brillig_solver = Some(solver); + Ok(Some(foreign_call)) + } + BrilligSolverStatus::InProgress => { + unreachable!("Brillig solver still in progress") + } + BrilligSolverStatus::Finished => { + // Write execution outputs + solver.finalize(witness, outputs)?; Ok(None) } } @@ -425,7 +480,8 @@ impl<'a, B: BlackBoxFunctionSolver> ACVM<'a, B> { }; if should_skip { - let resolution = BrilligSolver::::zero_out_brillig_outputs(witness, brillig); + let resolution = + BrilligSolver::::zero_out_brillig_outputs(witness, &brillig.outputs); return StepResult::Status(self.handle_opcode_resolution(resolution)); } diff --git a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs index ec7a6467ff5..f009e2c05b8 100644 --- a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs +++ b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs @@ -104,8 +104,9 @@ fn inversion_brillig_oracle_equivalence() { (Witness(2), FieldElement::from(3u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![]; + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -241,8 +242,9 @@ fn double_inversion_brillig_oracle() { (Witness(9), FieldElement::from(10u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![]; + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -370,8 +372,9 @@ fn oracle_dependent_execution() { let witness_assignments = BTreeMap::from([(w_x, FieldElement::from(2u128)), (w_y, FieldElement::from(2u128))]).into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![]; + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); // use the partial witness generation solver with our acir program let solver_status = acvm.solve(); @@ -474,8 +477,9 @@ fn brillig_oracle_predicate() { (Witness(2), FieldElement::from(3u128)), ]) .into(); - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments); + let unconstrained_functions = vec![]; + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, witness_assignments, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); @@ -509,7 +513,8 @@ fn unsatisfied_opcode_resolved() { values.insert(d, FieldElement::from(2_i128)); let opcodes = vec![Opcode::AssertZero(opcode_a)]; - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!( solver_status, @@ -591,8 +596,8 @@ fn unsatisfied_opcode_resolved_brillig() { values.insert(w_result, FieldElement::from(0_i128)); let opcodes = vec![brillig_opcode, Opcode::AssertZero(opcode_a)]; - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values); + let unconstrained_functions = vec![]; + let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, values, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!( solver_status, @@ -635,8 +640,9 @@ fn memory_operations() { }); let opcodes = vec![init, read_op, expression]; - - let mut acvm = ACVM::new(&StubbedBlackBoxSolver, &opcodes, initial_witness); + let unconstrained_functions = vec![]; + let mut acvm = + ACVM::new(&StubbedBlackBoxSolver, &opcodes, initial_witness, &unconstrained_functions); let solver_status = acvm.solve(); assert_eq!(solver_status, ACVMStatus::Solved); let witness_map = acvm.finalize(); diff --git a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs index 8bc56295992..2fab684467e 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs +++ b/noir/noir-repo/acvm-repo/acvm_js/src/execute.rs @@ -1,5 +1,6 @@ use std::{future::Future, pin::Pin}; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::BlackBoxFunctionSolver; use acvm::{ acir::circuit::{Circuit, Program}, @@ -181,7 +182,12 @@ async fn execute_program_with_native_program_and_return( initial_witness: JsWitnessMap, foreign_call_executor: &ForeignCallHandler, ) -> Result { - let executor = ProgramExecutor::new(&program.functions, &solver.0, foreign_call_executor); + let executor = ProgramExecutor::new( + &program.functions, + &program.unconstrained_functions, + &solver.0, + foreign_call_executor, + ); let witness_stack = executor.execute(initial_witness.into()).await?; Ok(witness_stack) @@ -190,6 +196,8 @@ async fn execute_program_with_native_program_and_return( struct ProgramExecutor<'a, B: BlackBoxFunctionSolver> { functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], + blackbox_solver: &'a B, foreign_call_handler: &'a ForeignCallHandler, @@ -198,10 +206,16 @@ struct ProgramExecutor<'a, B: BlackBoxFunctionSolver> { impl<'a, B: BlackBoxFunctionSolver> ProgramExecutor<'a, B> { fn new( functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], blackbox_solver: &'a B, foreign_call_handler: &'a ForeignCallHandler, ) -> Self { - ProgramExecutor { functions, blackbox_solver, foreign_call_handler } + ProgramExecutor { + functions, + unconstrained_functions, + blackbox_solver, + foreign_call_handler, + } } async fn execute(&self, initial_witness: WitnessMap) -> Result { @@ -220,7 +234,12 @@ impl<'a, B: BlackBoxFunctionSolver> ProgramExecutor<'a, B> { witness_stack: &'a mut WitnessStack, ) -> Pin> + 'a>> { Box::pin(async { - let mut acvm = ACVM::new(self.blackbox_solver, &circuit.opcodes, initial_witness); + let mut acvm = ACVM::new( + self.blackbox_solver, + &circuit.opcodes, + initial_witness, + self.unconstrained_functions, + ); loop { let solver_status = acvm.solve(); diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml index d093b24a129..1d6629c8223 100644 --- a/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml +++ b/noir/noir-repo/acvm-repo/blackbox_solver/Cargo.toml @@ -15,6 +15,7 @@ repository.workspace = true [dependencies] acir.workspace = true thiserror.workspace = true +num-bigint = "0.4" blake2 = "0.10.6" blake3 = "1.5.0" diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/src/bigint.rs b/noir/noir-repo/acvm-repo/blackbox_solver/src/bigint.rs new file mode 100644 index 00000000000..5b19f03a238 --- /dev/null +++ b/noir/noir-repo/acvm-repo/blackbox_solver/src/bigint.rs @@ -0,0 +1,99 @@ +use std::collections::HashMap; + +use acir::BlackBoxFunc; + +use num_bigint::BigUint; + +use crate::BlackBoxResolutionError; + +/// Resolve BigInt opcodes by storing BigInt values (and their moduli) by their ID in a HashMap: +/// - When it encounters a bigint operation opcode, it performs the operation on the stored values +/// and store the result using the provided ID. +/// - When it gets a to_bytes opcode, it simply looks up the value and resolves the output witness accordingly. +#[derive(Default, Debug, Clone, PartialEq, Eq)] + +pub struct BigIntSolver { + bigint_id_to_value: HashMap, + bigint_id_to_modulus: HashMap, +} + +impl BigIntSolver { + pub(crate) fn get_bigint( + &self, + id: u32, + func: BlackBoxFunc, + ) -> Result { + self.bigint_id_to_value + .get(&id) + .ok_or(BlackBoxResolutionError::Failed( + func, + format!("could not find bigint of id {id}"), + )) + .cloned() + } + + pub(crate) fn get_modulus( + &self, + id: u32, + func: BlackBoxFunc, + ) -> Result { + self.bigint_id_to_modulus + .get(&id) + .ok_or(BlackBoxResolutionError::Failed( + func, + format!("could not find bigint of id {id}"), + )) + .cloned() + } + pub fn bigint_from_bytes( + &mut self, + inputs: &[u8], + modulus: &[u8], + output: u32, + ) -> Result<(), BlackBoxResolutionError> { + let bigint = BigUint::from_bytes_le(inputs); + self.bigint_id_to_value.insert(output, bigint); + let modulus = BigUint::from_bytes_le(modulus); + self.bigint_id_to_modulus.insert(output, modulus); + Ok(()) + } + + pub fn bigint_to_bytes(&self, input: u32) -> Result, BlackBoxResolutionError> { + let bigint = self.get_bigint(input, BlackBoxFunc::BigIntToLeBytes)?; + Ok(bigint.to_bytes_le()) + } + + pub fn bigint_op( + &mut self, + lhs: u32, + rhs: u32, + output: u32, + func: BlackBoxFunc, + ) -> Result<(), BlackBoxResolutionError> { + let modulus = self.get_modulus(lhs, func)?; + let lhs = self.get_bigint(lhs, func)?; + let rhs = self.get_bigint(rhs, func)?; + let mut result = match func { + BlackBoxFunc::BigIntAdd => lhs + rhs, + BlackBoxFunc::BigIntSub => { + if lhs >= rhs { + &lhs - &rhs + } else { + &lhs + &modulus - &rhs + } + } + BlackBoxFunc::BigIntMul => lhs * rhs, + BlackBoxFunc::BigIntDiv => { + lhs * rhs.modpow(&(&modulus - BigUint::from(2_u32)), &modulus) + } //TODO ensure that modulus is prime + _ => unreachable!("ICE - bigint_op must be called for an operation"), + }; + if result > modulus { + let q = &result / &modulus; + result -= q * &modulus; + } + self.bigint_id_to_value.insert(output, result); + self.bigint_id_to_modulus.insert(output, modulus); + Ok(()) + } +} diff --git a/noir/noir-repo/acvm-repo/blackbox_solver/src/lib.rs b/noir/noir-repo/acvm-repo/blackbox_solver/src/lib.rs index dc798bdab32..0f57f2ce7da 100644 --- a/noir/noir-repo/acvm-repo/blackbox_solver/src/lib.rs +++ b/noir/noir-repo/acvm-repo/blackbox_solver/src/lib.rs @@ -10,10 +10,12 @@ use acir::BlackBoxFunc; use thiserror::Error; +mod bigint; mod curve_specific_solver; mod ecdsa; mod hash; +pub use bigint::BigIntSolver; pub use curve_specific_solver::{BlackBoxFunctionSolver, StubbedBlackBoxSolver}; pub use ecdsa::{ecdsa_secp256k1_verify, ecdsa_secp256r1_verify}; pub use hash::{blake2s, blake3, keccak256, keccakf1600, sha256, sha256compression}; diff --git a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml index 318833180ea..448642e1a9e 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/Cargo.toml @@ -16,8 +16,9 @@ repository.workspace = true acir.workspace = true acvm_blackbox_solver.workspace = true thiserror.workspace = true -num-traits.workspace = true cfg-if = "1.0.0" +hex.workspace = true +lazy_static = "1.4" # BN254 fixed base scalar multiplication solver grumpkin = { version = "0.1.0", package = "noir_grumpkin", features = ["std"] } @@ -38,6 +39,18 @@ js-sys.workspace = true getrandom.workspace = true wasmer = "4.2.6" +[dev-dependencies] +criterion = "0.5.0" +pprof = { version = "0.12", features = [ + "flamegraph", + "frame-pointer", + "criterion", +] } + +[[bench]] +name = "criterion" +harness = false + [features] default = ["bn254"] bn254 = ["acir/bn254"] diff --git a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/benches/criterion.rs b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/benches/criterion.rs new file mode 100644 index 00000000000..eb529ed2c11 --- /dev/null +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/benches/criterion.rs @@ -0,0 +1,21 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use std::{hint::black_box, time::Duration}; + +use acir::FieldElement; +use bn254_blackbox_solver::poseidon2_permutation; + +use pprof::criterion::{Output, PProfProfiler}; + +fn bench_poseidon2(c: &mut Criterion) { + let inputs = [FieldElement::zero(); 4]; + + c.bench_function("poseidon2", |b| b.iter(|| poseidon2_permutation(black_box(&inputs), 4))); +} + +criterion_group!( + name = benches; + config = Criterion::default().sample_size(40).measurement_time(Duration::from_secs(20)).with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); + targets = bench_poseidon2 +); + +criterion_main!(benches); diff --git a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs index 5e68c7d4030..cd91c290f49 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/fixed_base_scalar_mul.rs @@ -47,17 +47,29 @@ pub fn fixed_base_scalar_mul( } } +fn create_point(x: FieldElement, y: FieldElement) -> Result { + let point = grumpkin::SWAffine::new_unchecked(x.into_repr(), y.into_repr()); + if !point.is_on_curve() { + return Err(format!("Point ({}, {}) is not on curve", x.to_hex(), y.to_hex())); + }; + if !point.is_in_correct_subgroup_assuming_on_curve() { + return Err(format!("Point ({}, {}) is not in correct subgroup", x.to_hex(), y.to_hex())); + }; + Ok(point) +} + pub fn embedded_curve_add( input1_x: FieldElement, input1_y: FieldElement, input2_x: FieldElement, input2_y: FieldElement, ) -> Result<(FieldElement, FieldElement), BlackBoxResolutionError> { - let mut point1 = grumpkin::SWAffine::new(input1_x.into_repr(), input1_y.into_repr()); - let point2 = grumpkin::SWAffine::new(input2_x.into_repr(), input2_y.into_repr()); - let res = point1 + point2; - point1 = res.into(); - if let Some((res_x, res_y)) = point1.xy() { + let point1 = create_point(input1_x, input1_y) + .map_err(|e| BlackBoxResolutionError::Failed(BlackBoxFunc::EmbeddedCurveAdd, e))?; + let point2 = create_point(input2_x, input2_y) + .map_err(|e| BlackBoxResolutionError::Failed(BlackBoxFunc::EmbeddedCurveAdd, e))?; + let res = grumpkin::SWAffine::from(point1 + point2); + if let Some((res_x, res_y)) = res.xy() { Ok((FieldElement::from_repr(*res_x), FieldElement::from_repr(*res_y))) } else { Err(BlackBoxResolutionError::Failed( @@ -72,6 +84,7 @@ mod grumpkin_fixed_base_scalar_mul { use ark_ff::BigInteger; use super::*; + #[test] fn smoke_test() -> Result<(), BlackBoxResolutionError> { let input = FieldElement::one(); @@ -84,6 +97,7 @@ mod grumpkin_fixed_base_scalar_mul { assert_eq!(y, res.1.to_hex()); Ok(()) } + #[test] fn low_high_smoke_test() -> Result<(), BlackBoxResolutionError> { let low = FieldElement::one(); @@ -103,9 +117,9 @@ mod grumpkin_fixed_base_scalar_mul { let max_limb = FieldElement::from(u128::MAX); let invalid_limb = max_limb + FieldElement::one(); - let expected_error = Err(BlackBoxResolutionError::Failed( + let expected_error = Err(BlackBoxResolutionError::Failed( BlackBoxFunc::FixedBaseScalarMul, - "Limb 0000000000000000000000000000000100000000000000000000000000000000 is not less than 2^128".into() + "Limb 0000000000000000000000000000000100000000000000000000000000000000 is not less than 2^128".into(), )); let res = fixed_base_scalar_mul(&invalid_limb, &FieldElement::zero()); @@ -128,7 +142,23 @@ mod grumpkin_fixed_base_scalar_mul { res, Err(BlackBoxResolutionError::Failed( BlackBoxFunc::FixedBaseScalarMul, - "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into() + "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 is not a valid grumpkin scalar".into(), + )) + ); + } + + #[test] + fn rejects_addition_of_points_not_in_curve() { + let x = FieldElement::from(1u128); + let y = FieldElement::from(2u128); + + let res = embedded_curve_add(x, y, x, y); + + assert_eq!( + res, + Err(BlackBoxResolutionError::Failed( + BlackBoxFunc::EmbeddedCurveAdd, + "Point (0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000002) is not on curve".into(), )) ); } diff --git a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/lib.rs b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/lib.rs index f7c303888e8..25b10252a78 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/lib.rs +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/lib.rs @@ -10,7 +10,7 @@ mod poseidon2; mod wasm; pub use fixed_base_scalar_mul::{embedded_curve_add, fixed_base_scalar_mul}; -use poseidon2::Poseidon2; +pub use poseidon2::poseidon2_permutation; use wasm::Barretenberg; use self::wasm::{Pedersen, SchnorrSig}; @@ -112,7 +112,6 @@ impl BlackBoxFunctionSolver for Bn254BlackBoxSolver { inputs: &[FieldElement], len: u32, ) -> Result, BlackBoxResolutionError> { - let poseidon = Poseidon2::new(); - poseidon.permutation(inputs, len) + poseidon2_permutation(inputs, len) } } diff --git a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs index e0ed5bcd053..65058e15099 100644 --- a/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs +++ b/noir/noir-repo/acvm-repo/bn254_blackbox_solver/src/poseidon2.rs @@ -1,9 +1,20 @@ use acir::FieldElement; use acvm_blackbox_solver::BlackBoxResolutionError; -use num_bigint::BigUint; -use num_traits::Num; +use lazy_static::lazy_static; -pub(crate) struct Poseidon2 { +pub fn poseidon2_permutation( + inputs: &[FieldElement], + len: u32, +) -> Result, BlackBoxResolutionError> { + let poseidon = Poseidon2::new(); + poseidon.permutation(inputs, len) +} + +pub(crate) struct Poseidon2<'a> { + config: &'a Poseidon2Config, +} + +struct Poseidon2Config { t: u32, rounds_f: u32, rounds_p: u32, @@ -11,929 +22,415 @@ pub(crate) struct Poseidon2 { round_constant: [[FieldElement; 4]; 64], } -impl Poseidon2 { +fn field_from_hex(hex: &str) -> FieldElement { + FieldElement::from_be_bytes_reduce(&hex::decode(hex).expect("Should be passed only valid hex")) +} + +lazy_static! { + static ref INTERNAL_MATRIX_DIAGONAL: [FieldElement; 4] = [ + field_from_hex("10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7"), + field_from_hex("0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b"), + field_from_hex("00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15"), + field_from_hex("222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b"), + ]; + static ref ROUND_CONSTANT: [[FieldElement; 4]; 64] = [ + [ + field_from_hex("19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5"), + field_from_hex("265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6"), + field_from_hex("199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa"), + field_from_hex("157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8"), + ], + [ + field_from_hex("2e49c43c4569dd9c5fd35ac45fca33f10b15c590692f8beefe18f4896ac94902"), + field_from_hex("0e35fb89981890520d4aef2b6d6506c3cb2f0b6973c24fa82731345ffa2d1f1e"), + field_from_hex("251ad47cb15c4f1105f109ae5e944f1ba9d9e7806d667ffec6fe723002e0b996"), + field_from_hex("13da07dc64d428369873e97160234641f8beb56fdd05e5f3563fa39d9c22df4e"), + ], + [ + field_from_hex("0c009b84e650e6d23dc00c7dccef7483a553939689d350cd46e7b89055fd4738"), + field_from_hex("011f16b1c63a854f01992e3956f42d8b04eb650c6d535eb0203dec74befdca06"), + field_from_hex("0ed69e5e383a688f209d9a561daa79612f3f78d0467ad45485df07093f367549"), + field_from_hex("04dba94a7b0ce9e221acad41472b6bbe3aec507f5eb3d33f463672264c9f789b"), + ], + [ + field_from_hex("0a3f2637d840f3a16eb094271c9d237b6036757d4bb50bf7ce732ff1d4fa28e8"), + field_from_hex("259a666f129eea198f8a1c502fdb38fa39b1f075569564b6e54a485d1182323f"), + field_from_hex("28bf7459c9b2f4c6d8e7d06a4ee3a47f7745d4271038e5157a32fdf7ede0d6a1"), + field_from_hex("0a1ca941f057037526ea200f489be8d4c37c85bbcce6a2aeec91bd6941432447"), + ], + [ + field_from_hex("0c6f8f958be0e93053d7fd4fc54512855535ed1539f051dcb43a26fd926361cf"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("123106a93cd17578d426e8128ac9d90aa9e8a00708e296e084dd57e69caaf811"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("26e1ba52ad9285d97dd3ab52f8e840085e8fa83ff1e8f1877b074867cd2dee75"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1cb55cad7bd133de18a64c5c47b9c97cbe4d8b7bf9e095864471537e6a4ae2c5"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1dcd73e46acd8f8e0e2c7ce04bde7f6d2a53043d5060a41c7143f08e6e9055d0"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("011003e32f6d9c66f5852f05474a4def0cda294a0eb4e9b9b12b9bb4512e5574"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2b1e809ac1d10ab29ad5f20d03a57dfebadfe5903f58bafed7c508dd2287ae8c"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2539de1785b735999fb4dac35ee17ed0ef995d05ab2fc5faeaa69ae87bcec0a5"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0c246c5a2ef8ee0126497f222b3e0a0ef4e1c3d41c86d46e43982cb11d77951d"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("192089c4974f68e95408148f7c0632edbb09e6a6ad1a1c2f3f0305f5d03b527b"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1eae0ad8ab68b2f06a0ee36eeb0d0c058529097d91096b756d8fdc2fb5a60d85"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("179190e5d0e22179e46f8282872abc88db6e2fdc0dee99e69768bd98c5d06bfb"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("29bb9e2c9076732576e9a81c7ac4b83214528f7db00f31bf6cafe794a9b3cd1c"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("225d394e42207599403efd0c2464a90d52652645882aac35b10e590e6e691e08"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("064760623c25c8cf753d238055b444532be13557451c087de09efd454b23fd59"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("10ba3a0e01df92e87f301c4b716d8a394d67f4bf42a75c10922910a78f6b5b87"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0e070bf53f8451b24f9c6e96b0c2a801cb511bc0c242eb9d361b77693f21471c"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1b94cd61b051b04dd39755ff93821a73ccd6cb11d2491d8aa7f921014de252fb"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1d7cb39bafb8c744e148787a2e70230f9d4e917d5713bb050487b5aa7d74070b"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2ec93189bd1ab4f69117d0fe980c80ff8785c2961829f701bb74ac1f303b17db"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2db366bfdd36d277a692bb825b86275beac404a19ae07a9082ea46bd83517926"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("062100eb485db06269655cf186a68532985275428450359adc99cec6960711b8"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0761d33c66614aaa570e7f1e8244ca1120243f92fa59e4f900c567bf41f5a59b"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("20fc411a114d13992c2705aa034e3f315d78608a0f7de4ccf7a72e494855ad0d"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("25b5c004a4bdfcb5add9ec4e9ab219ba102c67e8b3effb5fc3a30f317250bc5a"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("23b1822d278ed632a494e58f6df6f5ed038b186d8474155ad87e7dff62b37f4b"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("22734b4c5c3f9493606c4ba9012499bf0f14d13bfcfcccaa16102a29cc2f69e0"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("26c0c8fe09eb30b7e27a74dc33492347e5bdff409aa3610254413d3fad795ce5"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("070dd0ccb6bd7bbae88eac03fa1fbb26196be3083a809829bbd626df348ccad9"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("12b6595bdb329b6fb043ba78bb28c3bec2c0a6de46d8c5ad6067c4ebfd4250da"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("248d97d7f76283d63bec30e7a5876c11c06fca9b275c671c5e33d95bb7e8d729"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1a306d439d463b0816fc6fd64cc939318b45eb759ddde4aa106d15d9bd9baaaa"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("28a8f8372e3c38daced7c00421cb4621f4f1b54ddc27821b0d62d3d6ec7c56cf"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0094975717f9a8a8bb35152f24d43294071ce320c829f388bc852183e1e2ce7e"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("04d5ee4c3aa78f7d80fde60d716480d3593f74d4f653ae83f4103246db2e8d65"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2a6cf5e9aa03d4336349ad6fb8ed2269c7bef54b8822cc76d08495c12efde187"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2304d31eaab960ba9274da43e19ddeb7f792180808fd6e43baae48d7efcba3f3"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("03fd9ac865a4b2a6d5e7009785817249bff08a7e0726fcb4e1c11d39d199f0b0"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("00b7258ded52bbda2248404d55ee5044798afc3a209193073f7954d4d63b0b64"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("159f81ada0771799ec38fca2d4bf65ebb13d3a74f3298db36272c5ca65e92d9a"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1ef90e67437fbc8550237a75bc28e3bb9000130ea25f0c5471e144cf4264431f"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1e65f838515e5ff0196b49aa41a2d2568df739bc176b08ec95a79ed82932e30d"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2b1b045def3a166cec6ce768d079ba74b18c844e570e1f826575c1068c94c33f"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0832e5753ceb0ff6402543b1109229c165dc2d73bef715e3f1c6e07c168bb173"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("02f614e9cedfb3dc6b762ae0a37d41bab1b841c2e8b6451bc5a8e3c390b6ad16"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0e2427d38bd46a60dd640b8e362cad967370ebb777bedff40f6a0be27e7ed705"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0493630b7c670b6deb7c84d414e7ce79049f0ec098c3c7c50768bbe29214a53a"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("22ead100e8e482674decdab17066c5a26bb1515355d5461a3dc06cc85327cea9"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("25b3e56e655b42cdaae2626ed2554d48583f1ae35626d04de5084e0b6d2a6f16"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1e32752ada8836ef5837a6cde8ff13dbb599c336349e4c584b4fdc0a0cf6f9d0"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2fa2a871c15a387cc50f68f6f3c3455b23c00995f05078f672a9864074d412e5"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("2f569b8a9a4424c9278e1db7311e889f54ccbf10661bab7fcd18e7c7a7d83505"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("044cb455110a8fdd531ade530234c518a7df93f7332ffd2144165374b246b43d"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("227808de93906d5d420246157f2e42b191fe8c90adfe118178ddc723a5319025"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("02fcca2934e046bc623adead873579865d03781ae090ad4a8579d2e7a6800355"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("0ef915f0ac120b876abccceb344a1d36bad3f3c5ab91a8ddcbec2e060d8befac"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + field_from_hex("0000000000000000000000000000000000000000000000000000000000000000"), + ], + [ + field_from_hex("1797130f4b7a3e1777eb757bc6f287f6ab0fb85f6be63b09f3b16ef2b1405d38"), + field_from_hex("0a76225dc04170ae3306c85abab59e608c7f497c20156d4d36c668555decc6e5"), + field_from_hex("1fffb9ec1992d66ba1e77a7b93209af6f8fa76d48acb664796174b5326a31a5c"), + field_from_hex("25721c4fc15a3f2853b57c338fa538d85f8fbba6c6b9c6090611889b797b9c5f"), + ], + [ + field_from_hex("0c817fd42d5f7a41215e3d07ba197216adb4c3790705da95eb63b982bfcaf75a"), + field_from_hex("13abe3f5239915d39f7e13c2c24970b6df8cf86ce00a22002bc15866e52b5a96"), + field_from_hex("2106feea546224ea12ef7f39987a46c85c1bc3dc29bdbd7a92cd60acb4d391ce"), + field_from_hex("21ca859468a746b6aaa79474a37dab49f1ca5a28c748bc7157e1b3345bb0f959"), + ], + [ + field_from_hex("05ccd6255c1e6f0c5cf1f0df934194c62911d14d0321662a8f1a48999e34185b"), + field_from_hex("0f0e34a64b70a626e464d846674c4c8816c4fb267fe44fe6ea28678cb09490a4"), + field_from_hex("0558531a4e25470c6157794ca36d0e9647dbfcfe350d64838f5b1a8a2de0d4bf"), + field_from_hex("09d3dca9173ed2faceea125157683d18924cadad3f655a60b72f5864961f1455"), + ], + [ + field_from_hex("0328cbd54e8c0913493f866ed03d218bf23f92d68aaec48617d4c722e5bd4335"), + field_from_hex("2bf07216e2aff0a223a487b1a7094e07e79e7bcc9798c648ee3347dd5329d34b"), + field_from_hex("1daf345a58006b736499c583cb76c316d6f78ed6a6dffc82111e11a63fe412df"), + field_from_hex("176563472456aaa746b694c60e1823611ef39039b2edc7ff391e6f2293d2c404"), + ], + ]; + static ref POSEIDON2_CONFIG: Poseidon2Config = Poseidon2Config { + t: 4, + rounds_f: 8, + rounds_p: 56, + internal_matrix_diagonal: *INTERNAL_MATRIX_DIAGONAL, + round_constant: *ROUND_CONSTANT, + }; +} + +impl<'a> Poseidon2<'a> { pub(crate) fn new() -> Self { - Poseidon2 { - t: 4, - rounds_f: 8, - rounds_p: 56, - internal_matrix_diagonal: [ - Poseidon2::field_from_hex( - "0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7", - ), - Poseidon2::field_from_hex( - "0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b", - ), - Poseidon2::field_from_hex( - "0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15", - ), - Poseidon2::field_from_hex( - "0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b", - ), - ], - round_constant: [ - [ - Poseidon2::field_from_hex( - "0x19b849f69450b06848da1d39bd5e4a4302bb86744edc26238b0878e269ed23e5", - ), - Poseidon2::field_from_hex( - "0x265ddfe127dd51bd7239347b758f0a1320eb2cc7450acc1dad47f80c8dcf34d6", - ), - Poseidon2::field_from_hex( - "0x199750ec472f1809e0f66a545e1e51624108ac845015c2aa3dfc36bab497d8aa", - ), - Poseidon2::field_from_hex( - "0x157ff3fe65ac7208110f06a5f74302b14d743ea25067f0ffd032f787c7f1cdf8", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2e49c43c4569dd9c5fd35ac45fca33f10b15c590692f8beefe18f4896ac94902", - ), - Poseidon2::field_from_hex( - "0x0e35fb89981890520d4aef2b6d6506c3cb2f0b6973c24fa82731345ffa2d1f1e", - ), - Poseidon2::field_from_hex( - "0x251ad47cb15c4f1105f109ae5e944f1ba9d9e7806d667ffec6fe723002e0b996", - ), - Poseidon2::field_from_hex( - "0x13da07dc64d428369873e97160234641f8beb56fdd05e5f3563fa39d9c22df4e", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0c009b84e650e6d23dc00c7dccef7483a553939689d350cd46e7b89055fd4738", - ), - Poseidon2::field_from_hex( - "0x011f16b1c63a854f01992e3956f42d8b04eb650c6d535eb0203dec74befdca06", - ), - Poseidon2::field_from_hex( - "0x0ed69e5e383a688f209d9a561daa79612f3f78d0467ad45485df07093f367549", - ), - Poseidon2::field_from_hex( - "0x04dba94a7b0ce9e221acad41472b6bbe3aec507f5eb3d33f463672264c9f789b", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0a3f2637d840f3a16eb094271c9d237b6036757d4bb50bf7ce732ff1d4fa28e8", - ), - Poseidon2::field_from_hex( - "0x259a666f129eea198f8a1c502fdb38fa39b1f075569564b6e54a485d1182323f", - ), - Poseidon2::field_from_hex( - "0x28bf7459c9b2f4c6d8e7d06a4ee3a47f7745d4271038e5157a32fdf7ede0d6a1", - ), - Poseidon2::field_from_hex( - "0x0a1ca941f057037526ea200f489be8d4c37c85bbcce6a2aeec91bd6941432447", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0c6f8f958be0e93053d7fd4fc54512855535ed1539f051dcb43a26fd926361cf", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x123106a93cd17578d426e8128ac9d90aa9e8a00708e296e084dd57e69caaf811", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x26e1ba52ad9285d97dd3ab52f8e840085e8fa83ff1e8f1877b074867cd2dee75", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1cb55cad7bd133de18a64c5c47b9c97cbe4d8b7bf9e095864471537e6a4ae2c5", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1dcd73e46acd8f8e0e2c7ce04bde7f6d2a53043d5060a41c7143f08e6e9055d0", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x011003e32f6d9c66f5852f05474a4def0cda294a0eb4e9b9b12b9bb4512e5574", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2b1e809ac1d10ab29ad5f20d03a57dfebadfe5903f58bafed7c508dd2287ae8c", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2539de1785b735999fb4dac35ee17ed0ef995d05ab2fc5faeaa69ae87bcec0a5", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0c246c5a2ef8ee0126497f222b3e0a0ef4e1c3d41c86d46e43982cb11d77951d", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x192089c4974f68e95408148f7c0632edbb09e6a6ad1a1c2f3f0305f5d03b527b", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1eae0ad8ab68b2f06a0ee36eeb0d0c058529097d91096b756d8fdc2fb5a60d85", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x179190e5d0e22179e46f8282872abc88db6e2fdc0dee99e69768bd98c5d06bfb", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x29bb9e2c9076732576e9a81c7ac4b83214528f7db00f31bf6cafe794a9b3cd1c", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x225d394e42207599403efd0c2464a90d52652645882aac35b10e590e6e691e08", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x064760623c25c8cf753d238055b444532be13557451c087de09efd454b23fd59", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x10ba3a0e01df92e87f301c4b716d8a394d67f4bf42a75c10922910a78f6b5b87", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0e070bf53f8451b24f9c6e96b0c2a801cb511bc0c242eb9d361b77693f21471c", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1b94cd61b051b04dd39755ff93821a73ccd6cb11d2491d8aa7f921014de252fb", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1d7cb39bafb8c744e148787a2e70230f9d4e917d5713bb050487b5aa7d74070b", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2ec93189bd1ab4f69117d0fe980c80ff8785c2961829f701bb74ac1f303b17db", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2db366bfdd36d277a692bb825b86275beac404a19ae07a9082ea46bd83517926", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x062100eb485db06269655cf186a68532985275428450359adc99cec6960711b8", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0761d33c66614aaa570e7f1e8244ca1120243f92fa59e4f900c567bf41f5a59b", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x20fc411a114d13992c2705aa034e3f315d78608a0f7de4ccf7a72e494855ad0d", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x25b5c004a4bdfcb5add9ec4e9ab219ba102c67e8b3effb5fc3a30f317250bc5a", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x23b1822d278ed632a494e58f6df6f5ed038b186d8474155ad87e7dff62b37f4b", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x22734b4c5c3f9493606c4ba9012499bf0f14d13bfcfcccaa16102a29cc2f69e0", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x26c0c8fe09eb30b7e27a74dc33492347e5bdff409aa3610254413d3fad795ce5", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x070dd0ccb6bd7bbae88eac03fa1fbb26196be3083a809829bbd626df348ccad9", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x12b6595bdb329b6fb043ba78bb28c3bec2c0a6de46d8c5ad6067c4ebfd4250da", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x248d97d7f76283d63bec30e7a5876c11c06fca9b275c671c5e33d95bb7e8d729", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1a306d439d463b0816fc6fd64cc939318b45eb759ddde4aa106d15d9bd9baaaa", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x28a8f8372e3c38daced7c00421cb4621f4f1b54ddc27821b0d62d3d6ec7c56cf", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0094975717f9a8a8bb35152f24d43294071ce320c829f388bc852183e1e2ce7e", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x04d5ee4c3aa78f7d80fde60d716480d3593f74d4f653ae83f4103246db2e8d65", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2a6cf5e9aa03d4336349ad6fb8ed2269c7bef54b8822cc76d08495c12efde187", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2304d31eaab960ba9274da43e19ddeb7f792180808fd6e43baae48d7efcba3f3", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x03fd9ac865a4b2a6d5e7009785817249bff08a7e0726fcb4e1c11d39d199f0b0", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x00b7258ded52bbda2248404d55ee5044798afc3a209193073f7954d4d63b0b64", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x159f81ada0771799ec38fca2d4bf65ebb13d3a74f3298db36272c5ca65e92d9a", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1ef90e67437fbc8550237a75bc28e3bb9000130ea25f0c5471e144cf4264431f", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1e65f838515e5ff0196b49aa41a2d2568df739bc176b08ec95a79ed82932e30d", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2b1b045def3a166cec6ce768d079ba74b18c844e570e1f826575c1068c94c33f", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0832e5753ceb0ff6402543b1109229c165dc2d73bef715e3f1c6e07c168bb173", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x02f614e9cedfb3dc6b762ae0a37d41bab1b841c2e8b6451bc5a8e3c390b6ad16", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0e2427d38bd46a60dd640b8e362cad967370ebb777bedff40f6a0be27e7ed705", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0493630b7c670b6deb7c84d414e7ce79049f0ec098c3c7c50768bbe29214a53a", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x22ead100e8e482674decdab17066c5a26bb1515355d5461a3dc06cc85327cea9", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x25b3e56e655b42cdaae2626ed2554d48583f1ae35626d04de5084e0b6d2a6f16", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1e32752ada8836ef5837a6cde8ff13dbb599c336349e4c584b4fdc0a0cf6f9d0", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2fa2a871c15a387cc50f68f6f3c3455b23c00995f05078f672a9864074d412e5", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x2f569b8a9a4424c9278e1db7311e889f54ccbf10661bab7fcd18e7c7a7d83505", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x044cb455110a8fdd531ade530234c518a7df93f7332ffd2144165374b246b43d", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x227808de93906d5d420246157f2e42b191fe8c90adfe118178ddc723a5319025", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x02fcca2934e046bc623adead873579865d03781ae090ad4a8579d2e7a6800355", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0ef915f0ac120b876abccceb344a1d36bad3f3c5ab91a8ddcbec2e060d8befac", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - Poseidon2::field_from_hex( - "0x0000000000000000000000000000000000000000000000000000000000000000", - ), - ], - [ - Poseidon2::field_from_hex( - "0x1797130f4b7a3e1777eb757bc6f287f6ab0fb85f6be63b09f3b16ef2b1405d38", - ), - Poseidon2::field_from_hex( - "0x0a76225dc04170ae3306c85abab59e608c7f497c20156d4d36c668555decc6e5", - ), - Poseidon2::field_from_hex( - "0x1fffb9ec1992d66ba1e77a7b93209af6f8fa76d48acb664796174b5326a31a5c", - ), - Poseidon2::field_from_hex( - "0x25721c4fc15a3f2853b57c338fa538d85f8fbba6c6b9c6090611889b797b9c5f", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0c817fd42d5f7a41215e3d07ba197216adb4c3790705da95eb63b982bfcaf75a", - ), - Poseidon2::field_from_hex( - "0x13abe3f5239915d39f7e13c2c24970b6df8cf86ce00a22002bc15866e52b5a96", - ), - Poseidon2::field_from_hex( - "0x2106feea546224ea12ef7f39987a46c85c1bc3dc29bdbd7a92cd60acb4d391ce", - ), - Poseidon2::field_from_hex( - "0x21ca859468a746b6aaa79474a37dab49f1ca5a28c748bc7157e1b3345bb0f959", - ), - ], - [ - Poseidon2::field_from_hex( - "0x05ccd6255c1e6f0c5cf1f0df934194c62911d14d0321662a8f1a48999e34185b", - ), - Poseidon2::field_from_hex( - "0x0f0e34a64b70a626e464d846674c4c8816c4fb267fe44fe6ea28678cb09490a4", - ), - Poseidon2::field_from_hex( - "0x0558531a4e25470c6157794ca36d0e9647dbfcfe350d64838f5b1a8a2de0d4bf", - ), - Poseidon2::field_from_hex( - "0x09d3dca9173ed2faceea125157683d18924cadad3f655a60b72f5864961f1455", - ), - ], - [ - Poseidon2::field_from_hex( - "0x0328cbd54e8c0913493f866ed03d218bf23f92d68aaec48617d4c722e5bd4335", - ), - Poseidon2::field_from_hex( - "0x2bf07216e2aff0a223a487b1a7094e07e79e7bcc9798c648ee3347dd5329d34b", - ), - Poseidon2::field_from_hex( - "0x1daf345a58006b736499c583cb76c316d6f78ed6a6dffc82111e11a63fe412df", - ), - Poseidon2::field_from_hex( - "0x176563472456aaa746b694c60e1823611ef39039b2edc7ff391e6f2293d2c404", - ), - ], - ], - } - } - fn field_from_hex(hex: &str) -> FieldElement { - let bigint = BigUint::from_str_radix(hex.strip_prefix("0x").unwrap(), 16).unwrap(); - FieldElement::from_be_bytes_reduce(&bigint.to_bytes_be()) + Poseidon2 { config: &POSEIDON2_CONFIG } } fn single_box(x: FieldElement) -> FieldElement { @@ -948,7 +445,9 @@ impl Poseidon2 { } fn add_round_constants(&self, state: &mut [FieldElement], round: usize) { - for (state_element, constant_element) in state.iter_mut().zip(self.round_constant[round]) { + for (state_element, constant_element) in + state.iter_mut().zip(self.config.round_constant[round]) + { *state_element += constant_element; } } @@ -982,7 +481,7 @@ impl Poseidon2 { sum += *i; } for (index, i) in input.iter_mut().enumerate() { - *i = *i * self.internal_matrix_diagonal[index]; + *i = *i * self.config.internal_matrix_diagonal[index]; *i += sum; } } @@ -1002,10 +501,10 @@ impl Poseidon2 { ), )); } - if len != self.t { + if len != self.config.t { return Err(BlackBoxResolutionError::Failed( acir::BlackBoxFunc::Poseidon2Permutation, - format!("Expected {} values but encountered {}", self.t, len), + format!("Expected {} values but encountered {}", self.config.t, len), )); } // Read witness assignments @@ -1017,22 +516,22 @@ impl Poseidon2 { Self::matrix_multiplication_4x4(&mut state); // First set of external rounds - let rf_first = self.rounds_f / 2; + let rf_first = self.config.rounds_f / 2; for r in 0..rf_first { self.add_round_constants(&mut state, r as usize); Self::s_box(&mut state); Self::matrix_multiplication_4x4(&mut state); } // Internal rounds - let p_end = rf_first + self.rounds_p; + let p_end = rf_first + self.config.rounds_p; for r in rf_first..p_end { - state[0] += self.round_constant[r as usize][0]; + state[0] += self.config.round_constant[r as usize][0]; state[0] = Self::single_box(state[0]); self.internal_m_multiplication(&mut state); } // Remaining external rounds - let num_rounds = self.rounds_f + self.rounds_p; + let num_rounds = self.config.rounds_f + self.config.rounds_p; for i in p_end..num_rounds { self.add_round_constants(&mut state, i as usize); Self::s_box(&mut state); @@ -1041,3 +540,24 @@ impl Poseidon2 { Ok(state.into()) } } + +#[cfg(test)] +mod test { + use acir::FieldElement; + + use super::{field_from_hex, poseidon2_permutation}; + + #[test] + fn smoke_test() { + let inputs = [FieldElement::zero(); 4]; + let result = poseidon2_permutation(&inputs, 4).expect("should successfully permute"); + + let expected_result = [ + field_from_hex("18DFB8DC9B82229CFF974EFEFC8DF78B1CE96D9D844236B496785C698BC6732E"), + field_from_hex("095C230D1D37A246E8D2D5A63B165FE0FADE040D442F61E25F0590E5FB76F839"), + field_from_hex("0BB9545846E1AFA4FA3C97414A60A20FC4949F537A68CCECA34C5CE71E28AA59"), + field_from_hex("18A4F34C9C6F99335FF7638B82AEED9018026618358873C982BBDDE265B2ED6D"), + ]; + assert_eq!(result, expected_result); + } +} diff --git a/noir/noir-repo/acvm-repo/brillig_vm/src/black_box.rs b/noir/noir-repo/acvm-repo/brillig_vm/src/black_box.rs index 2857e27f1af..19407da52db 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/src/black_box.rs +++ b/noir/noir-repo/acvm-repo/brillig_vm/src/black_box.rs @@ -1,5 +1,6 @@ use acir::brillig::{BlackBoxOp, HeapArray, HeapVector}; use acir::{BlackBoxFunc, FieldElement}; +use acvm_blackbox_solver::BigIntSolver; use acvm_blackbox_solver::{ blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccak256, keccakf1600, sha256, sha256compression, BlackBoxFunctionSolver, BlackBoxResolutionError, @@ -34,6 +35,7 @@ pub(crate) fn evaluate_black_box( op: &BlackBoxOp, solver: &Solver, memory: &mut Memory, + bigint_solver: &mut BigIntSolver, ) -> Result<(), BlackBoxResolutionError> { match op { BlackBoxOp::Sha256 { message, output } => { @@ -178,12 +180,57 @@ pub(crate) fn evaluate_black_box( memory.write(*output, hash.into()); Ok(()) } - BlackBoxOp::BigIntAdd { .. } => todo!(), - BlackBoxOp::BigIntSub { .. } => todo!(), - BlackBoxOp::BigIntMul { .. } => todo!(), - BlackBoxOp::BigIntDiv { .. } => todo!(), - BlackBoxOp::BigIntFromLeBytes { .. } => todo!(), - BlackBoxOp::BigIntToLeBytes { .. } => todo!(), + BlackBoxOp::BigIntAdd { lhs, rhs, output } => { + let lhs = memory.read(*lhs).try_into().unwrap(); + let rhs = memory.read(*rhs).try_into().unwrap(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_op(lhs, rhs, output, BlackBoxFunc::BigIntAdd)?; + Ok(()) + } + BlackBoxOp::BigIntSub { lhs, rhs, output } => { + let lhs = memory.read(*lhs).try_into().unwrap(); + let rhs = memory.read(*rhs).try_into().unwrap(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_op(lhs, rhs, output, BlackBoxFunc::BigIntSub)?; + Ok(()) + } + BlackBoxOp::BigIntMul { lhs, rhs, output } => { + let lhs = memory.read(*lhs).try_into().unwrap(); + let rhs = memory.read(*rhs).try_into().unwrap(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_op(lhs, rhs, output, BlackBoxFunc::BigIntMul)?; + Ok(()) + } + BlackBoxOp::BigIntDiv { lhs, rhs, output } => { + let lhs = memory.read(*lhs).try_into().unwrap(); + let rhs = memory.read(*rhs).try_into().unwrap(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_op(lhs, rhs, output, BlackBoxFunc::BigIntDiv)?; + Ok(()) + } + BlackBoxOp::BigIntFromLeBytes { inputs, modulus, output } => { + let input = read_heap_vector(memory, inputs); + let input: Vec = input.iter().map(|x| x.try_into().unwrap()).collect(); + let modulus = read_heap_vector(memory, modulus); + let modulus: Vec = modulus.iter().map(|x| x.try_into().unwrap()).collect(); + let output = memory.read(*output).try_into().unwrap(); + bigint_solver.bigint_from_bytes(&input, &modulus, output)?; + Ok(()) + } + BlackBoxOp::BigIntToLeBytes { input, output } => { + let input: u32 = memory.read(*input).try_into().unwrap(); + let bytes = bigint_solver.bigint_to_bytes(input)?; + let mut values = Vec::new(); + for i in 0..32 { + if i < bytes.len() { + values.push(bytes[i].into()); + } else { + values.push(0_u8.into()); + } + } + memory.write_slice(memory.read_ref(output.pointer), &values); + Ok(()) + } BlackBoxOp::Poseidon2Permutation { message, output, len } => { let input = read_heap_vector(memory, message); let input: Vec = input.iter().map(|x| x.try_into().unwrap()).collect(); @@ -257,7 +304,7 @@ fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc { #[cfg(test)] mod test { use acir::brillig::{BlackBoxOp, MemoryAddress}; - use acvm_blackbox_solver::StubbedBlackBoxSolver; + use acvm_blackbox_solver::{BigIntSolver, StubbedBlackBoxSolver}; use crate::{ black_box::{evaluate_black_box, to_u8_vec, to_value_vec}, @@ -282,7 +329,8 @@ mod test { output: HeapArray { pointer: 2.into(), size: 32 }, }; - evaluate_black_box(&op, &StubbedBlackBoxSolver, &mut memory).unwrap(); + evaluate_black_box(&op, &StubbedBlackBoxSolver, &mut memory, &mut BigIntSolver::default()) + .unwrap(); let result = memory.read_slice(MemoryAddress(result_pointer), 32); diff --git a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs index d83870dc410..75299670f94 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs +++ b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs @@ -16,7 +16,7 @@ use acir::brillig::{ HeapVector, MemoryAddress, Opcode, ValueOrArray, }; use acir::FieldElement; -use acvm_blackbox_solver::BlackBoxFunctionSolver; +use acvm_blackbox_solver::{BigIntSolver, BlackBoxFunctionSolver}; use arithmetic::{evaluate_binary_field_op, evaluate_binary_int_op, BrilligArithmeticError}; use black_box::evaluate_black_box; use num_bigint::BigUint; @@ -87,6 +87,8 @@ pub struct VM<'a, B: BlackBoxFunctionSolver> { call_stack: Vec, /// The solver for blackbox functions black_box_solver: &'a B, + // The solver for big integers + bigint_solver: BigIntSolver, } impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { @@ -107,6 +109,7 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { memory: Memory::default(), call_stack: Vec::new(), black_box_solver, + bigint_solver: Default::default(), } } @@ -334,7 +337,12 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { self.increment_program_counter() } Opcode::BlackBox(black_box_op) => { - match evaluate_black_box(black_box_op, self.black_box_solver, &mut self.memory) { + match evaluate_black_box( + black_box_op, + self.black_box_solver, + &mut self.memory, + &mut self.bigint_solver, + ) { Ok(()) => self.increment_program_counter(), Err(e) => self.fail(e.to_string()), } diff --git a/noir/noir-repo/aztec_macros/src/lib.rs b/noir/noir-repo/aztec_macros/src/lib.rs index 48c30ab6ffa..dff3193a327 100644 --- a/noir/noir-repo/aztec_macros/src/lib.rs +++ b/noir/noir-repo/aztec_macros/src/lib.rs @@ -3,6 +3,9 @@ mod utils; use transforms::{ compute_note_hash_and_nullifier::inject_compute_note_hash_and_nullifier, + contract_interface::{ + generate_contract_interface, stub_function, update_fn_signatures_in_contract_interface, + }, events::{generate_selector_impl, transform_events}, functions::{export_fn_abi, transform_function, transform_unconstrained}, note_interface::{generate_note_interface_impl, inject_note_exports}, @@ -59,7 +62,14 @@ fn transform( // Usage -> mut ast -> aztec_library::transform(&mut ast) // Covers all functions in the ast for submodule in ast.submodules.iter_mut().filter(|submodule| submodule.is_contract) { - if transform_module(&mut submodule.contents).map_err(|err| (err.into(), file_id))? { + if transform_module( + crate_id, + context, + &mut submodule.contents, + submodule.name.0.contents.as_str(), + ) + .map_err(|err| (err.into(), file_id))? + { check_for_aztec_dependency(crate_id, context)?; } } @@ -72,7 +82,12 @@ fn transform( /// Determines if ast nodes are annotated with aztec attributes. /// For annotated functions it calls the `transform` function which will perform the required transformations. /// Returns true if an annotated node is found, false otherwise -fn transform_module(module: &mut SortedModule) -> Result { +fn transform_module( + crate_id: &CrateId, + context: &HirContext, + module: &mut SortedModule, + module_name: &str, +) -> Result { let mut has_transformed_module = false; // Check for a user defined storage struct @@ -84,7 +99,12 @@ fn transform_module(module: &mut SortedModule) -> Result if !check_for_storage_implementation(module, &storage_struct_name) { generate_storage_implementation(module, &storage_struct_name)?; } - generate_storage_layout(module, storage_struct_name)?; + // Make sure we're only generating the storage layout for the root crate + // In case we got a contract importing other contracts for their interface, we + // don't want to generate the storage layout for them + if crate_id == context.root_crate_id() { + generate_storage_layout(module, storage_struct_name)?; + } } for structure in module.types.iter_mut() { @@ -102,6 +122,8 @@ fn transform_module(module: &mut SortedModule) -> Result .any(|attr| is_custom_attribute(attr, "aztec(initializer)")) }); + let mut stubs: Vec<_> = vec![]; + for func in module.functions.iter_mut() { let mut is_private = false; let mut is_public = false; @@ -129,15 +151,18 @@ fn transform_module(module: &mut SortedModule) -> Result // Apply transformations to the function based on collected attributes if is_private || is_public || is_public_vm { + let fn_type = if is_private { + "Private" + } else if is_public_vm { + "Avm" + } else { + "Public" + }; + stubs.push(stub_function(fn_type, func)); + export_fn_abi(&mut module.types, func)?; transform_function( - if is_private { - "Private" - } else if is_public_vm { - "Avm" - } else { - "Public" - }, + fn_type, func, storage_defined, is_initializer, @@ -171,6 +196,8 @@ fn transform_module(module: &mut SortedModule) -> Result span: Span::default(), }); } + + generate_contract_interface(module, module_name, &stubs)?; } Ok(has_transformed_module) @@ -189,7 +216,8 @@ fn transform_hir( transform_events(crate_id, context)?; inject_compute_note_hash_and_nullifier(crate_id, context)?; assign_storage_slots(crate_id, context)?; - inject_note_exports(crate_id, context) + inject_note_exports(crate_id, context)?; + update_fn_signatures_in_contract_interface(crate_id, context) } else { Ok(()) } diff --git a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs index 1b6630935d9..4ff97a5dcae 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/compute_note_hash_and_nullifier.rs @@ -49,20 +49,20 @@ pub fn inject_compute_note_hash_and_nullifier( crate_id: &CrateId, context: &mut HirContext, ) -> Result<(), (AztecMacroError, FileId)> { - if let Some((module_id, file_id)) = get_contract_module_data(context, crate_id) { + if let Some((_, module_id, file_id)) = get_contract_module_data(context, crate_id) { // If compute_note_hash_and_nullifier is already defined by the user, we skip auto-generation in order to provide an // escape hatch for this mechanism. // TODO(#4647): improve this diagnosis and error messaging. - if check_for_compute_note_hash_and_nullifier_definition(crate_id, context) { + if context.crate_graph.root_crate_id() != crate_id + || check_for_compute_note_hash_and_nullifier_definition(crate_id, context) + { return Ok(()); } // In order to implement compute_note_hash_and_nullifier, we need to know all of the different note types the // contract might use. These are the types that are marked as #[aztec(note)]. - let note_types = fetch_notes(context) - .iter() - .map(|(_, note)| note.borrow().name.0.contents.clone()) - .collect::>(); + let note_types = + fetch_notes(context).iter().map(|(path, _)| path.to_string()).collect::>(); // We can now generate a version of compute_note_hash_and_nullifier tailored for the contract in this crate. let func = generate_compute_note_hash_and_nullifier(¬e_types); @@ -73,7 +73,14 @@ pub fn inject_compute_note_hash_and_nullifier( // pass an empty span. This function should not produce errors anyway so this should not matter. let location = Location::new(Span::empty(0), file_id); - inject_fn(crate_id, context, func, location, module_id, file_id); + inject_fn(crate_id, context, func, location, module_id, file_id).map_err(|err| { + ( + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { + secondary_message: err.secondary_message, + }, + file_id, + ) + })?; } Ok(()) } @@ -100,7 +107,7 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &[String]) -> Str // so we include a dummy version. " unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, + contract_address: dep::aztec::protocol_types::address::AztecAddress, nonce: Field, storage_slot: Field, note_type_id: Field, @@ -130,7 +137,7 @@ fn generate_compute_note_hash_and_nullifier_source(note_types: &[String]) -> Str format!( " unconstrained fn compute_note_hash_and_nullifier( - contract_address: AztecAddress, + contract_address: dep::aztec::protocol_types::address::AztecAddress, nonce: Field, storage_slot: Field, note_type_id: Field, diff --git a/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs new file mode 100644 index 00000000000..4401c867df9 --- /dev/null +++ b/noir/noir-repo/aztec_macros/src/transforms/contract_interface.rs @@ -0,0 +1,326 @@ +use noirc_frontend::{ + graph::CrateId, + macros_api::{FileId, HirContext, HirExpression, HirLiteral, HirStatement}, + parse_program, + parser::SortedModule, + NoirFunction, Type, UnresolvedTypeData, +}; + +use crate::utils::{ + constants::SELECTOR_PLACEHOLDER, + errors::AztecMacroError, + hir_utils::{collect_crate_structs, get_contract_module_data, signature_of_type}, +}; + +// Generates the stubs for contract functions as low level calls using CallInterface, turning +// #[aztec(public)] // also private +// fn a_function(first_arg: Field, second_arg: Struct, third_arg: [Field; 4]) -> Field { +// ... +// } +// +// into +// +// pub fn a_function(self, first_arg: Field, second_arg: Struct, third_arg: [Field; 4]) -> PublicCallInterface { +// let mut args_acc: [Field] = &[]; +// args_acc = args_acc.append(first_arg.serialize().as_slice()); +// args_acc = args_acc.append(second_arg.serialize().as_slice()); +// let hash_third_arg = third_arg.map(|x: Field| x.serialize()); +// for i in 0..third_arg.len() { +// args_acc = args_acc.append(third_arg[i].serialize().as_slice()); +// } +// let args_hash = dep::aztec::hash::hash_args(args_acc); +// assert(args_hash == dep::aztec::oracle::arguments::pack_arguments(args_acc)); +// PublicCallInterface { +// target_contract: self.target_contract, +// selector: FunctionSelector::from_signature("SELECTOR_PLACEHOLDER"), +// args_hash +// } +// } +// +// The selector placeholder has to be replaced with the actual function signature after type checking in the next macro pass +pub fn stub_function(aztec_visibility: &str, func: &NoirFunction) -> String { + let fn_name = func.name().to_string(); + let fn_parameters = func + .parameters() + .iter() + .map(|param| { + format!( + "{}: {}", + param.pattern.name_ident().0.contents, + param.typ.to_string().replace("plain::", "") + ) + }) + .collect::>() + .join(", "); + let fn_return_type: noirc_frontend::UnresolvedType = func.return_type(); + + let fn_selector = format!("dep::aztec::protocol_types::abis::function_selector::FunctionSelector::from_signature(\"{}\")", SELECTOR_PLACEHOLDER); + + let parameters = func.parameters(); + let is_void = if matches!(fn_return_type.typ, UnresolvedTypeData::Unit) { "Void" } else { "" }; + let return_type_hint = if is_void == "Void" { + "".to_string() + } else { + format!("<{}>", fn_return_type.typ.to_string().replace("plain::", "")) + }; + let call_args = parameters + .iter() + .map(|arg| { + let param_name = arg.pattern.name_ident().0.contents.clone(); + match &arg.typ.typ { + UnresolvedTypeData::Array(_, typ) => { + format!( + "let hash_{0} = {0}.map(|x: {1}| x.serialize()); + for i in 0..{0}.len() {{ + args_acc = args_acc.append(hash_{0}[i].as_slice()); + }}\n", + param_name, typ.typ + ) + } + _ => { + format!("args_acc = args_acc.append({}.serialize().as_slice());\n", param_name) + } + } + }) + .collect::>() + .join(""); + if aztec_visibility != "Avm" { + let args_hash = if !parameters.is_empty() { + format!( + "let mut args_acc: [Field] = &[]; + {} + let args_hash = dep::aztec::hash::hash_args(args_acc); + assert(args_hash == dep::aztec::oracle::arguments::pack_arguments(args_acc));", + call_args + ) + } else { + "let args_hash = 0;".to_string() + }; + + let fn_body = format!( + "{} + dep::aztec::context::{}{}CallInterface {{ + target_contract: self.target_contract, + selector: {}, + args_hash, + }}", + args_hash, aztec_visibility, is_void, fn_selector, + ); + format!( + "pub fn {}(self, {}) -> dep::aztec::context::{}{}CallInterface{} {{ + {} + }}", + fn_name, fn_parameters, aztec_visibility, is_void, return_type_hint, fn_body + ) + } else { + let args = format!( + "let mut args_acc: [Field] = &[]; + {} + ", + call_args + ); + let fn_body = format!( + "{} + dep::aztec::context::Avm{}CallInterface {{ + target_contract: self.target_contract, + selector: {}, + args: args_acc, + }}", + args, is_void, fn_selector, + ); + format!( + "pub fn {}(self, {}) -> dep::aztec::context::Avm{}CallInterface{} {{ + {} + }}", + fn_name, fn_parameters, is_void, return_type_hint, fn_body + ) + } +} + +// Generates the contract interface as a struct with an `at` function that holds the stubbed functions and provides +// them with a target contract address. The struct has the same name as the contract (which is technically a module) +// so imports look nice. The `at` function is also exposed as a contract library method for external use. +pub fn generate_contract_interface( + module: &mut SortedModule, + module_name: &str, + stubs: &[String], +) -> Result<(), AztecMacroError> { + let contract_interface = format!( + " + struct {0} {{ + target_contract: dep::aztec::protocol_types::address::AztecAddress + }} + + impl {0} {{ + {1} + + pub fn at( + target_contract: dep::aztec::protocol_types::address::AztecAddress + ) -> Self {{ + Self {{ target_contract }} + }} + }} + + #[contract_library_method] + pub fn at( + target_contract: dep::aztec::protocol_types::address::AztecAddress + ) -> {0} {{ + {0} {{ target_contract }} + }} + ", + module_name, + stubs.join("\n"), + ); + + let (contract_interface_ast, errors) = parse_program(&contract_interface); + if !errors.is_empty() { + dbg!(errors); + return Err(AztecMacroError::CouldNotGenerateContractInterface { secondary_message: Some("Failed to parse Noir macro code during contract interface generation. This is either a bug in the compiler or the Noir macro code".to_string()), }); + } + + let mut contract_interface_ast = contract_interface_ast.into_sorted(); + module.types.push(contract_interface_ast.types.pop().unwrap()); + module.impls.push(contract_interface_ast.impls.pop().unwrap()); + module.functions.push(contract_interface_ast.functions.pop().unwrap()); + + Ok(()) +} + +fn compute_fn_signature(fn_name: &str, parameters: &[Type]) -> String { + format!( + "{}({})", + fn_name, + parameters.iter().map(signature_of_type).collect::>().join(",") + ) +} + +// Updates the function signatures in the contract interface with the actual ones, replacing the placeholder. +// This is done by locating the contract interface struct, its functions (stubs) and assuming the last statement of each +// is the constructor for a CallInterface. This constructor has a selector field that holds a +// FunctionSelector::from_signature function that receives the signature as a string literal. +pub fn update_fn_signatures_in_contract_interface( + crate_id: &CrateId, + context: &mut HirContext, +) -> Result<(), (AztecMacroError, FileId)> { + if let Some((name, _, file_id)) = get_contract_module_data(context, crate_id) { + let maybe_interface_struct = + collect_crate_structs(crate_id, context).iter().find_map(|struct_id| { + let r#struct = context.def_interner.get_struct(*struct_id); + if r#struct.borrow().name.0.contents == name { + Some(r#struct) + } else { + None + } + }); + + if let Some(interface_struct) = maybe_interface_struct { + let methods = context.def_interner.get_struct_methods(interface_struct.borrow().id); + + for func_id in methods.iter().flat_map(|methods| methods.direct.iter()) { + let name = context.def_interner.function_name(func_id); + let fn_parameters = &context.def_interner.function_meta(func_id).parameters.clone(); + + if name == "at" { + continue; + } + + let fn_signature = compute_fn_signature( + name, + &fn_parameters + .iter() + .skip(1) + .map(|(_, typ, _)| typ.clone()) + .collect::>(), + ); + let hir_func = context.def_interner.function(func_id).block(&context.def_interner); + let call_interface_constructor_statement = context.def_interner.statement( + hir_func + .statements() + .last() + .ok_or((AztecMacroError::AztecDepNotFound, file_id))?, + ); + let call_interface_constructor_expression = + match call_interface_constructor_statement { + HirStatement::Expression(expression_id) => { + match context.def_interner.expression(&expression_id) { + HirExpression::Constructor(hir_constructor_expression) => { + Ok(hir_constructor_expression) + } + _ => Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some( + "CallInterface constructor statement must be a constructor expression" + .to_string(), + ), + }, + file_id, + )), + } + } + _ => Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some( + "CallInterface constructor statement must be an expression" + .to_string(), + ), + }, + file_id, + )), + }?; + let (_, function_selector_expression_id) = + call_interface_constructor_expression.fields[1]; + let function_selector_expression = + context.def_interner.expression(&function_selector_expression_id); + + let current_fn_signature_expression_id = match function_selector_expression { + HirExpression::Call(call_expr) => Ok(call_expr.arguments[0]), + _ => Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some( + "Function selector argument expression must be call expression" + .to_string(), + ), + }, + file_id, + )), + }?; + + let current_fn_signature_expression = + context.def_interner.expression(¤t_fn_signature_expression_id); + + match current_fn_signature_expression { + HirExpression::Literal(HirLiteral::Str(signature)) => { + if signature != SELECTOR_PLACEHOLDER { + Err(( + AztecMacroError::CouldNotGenerateContractInterface { + secondary_message: Some(format!( + "Function signature argument must be a placeholder: {}", + SELECTOR_PLACEHOLDER + )), + }, + file_id, + )) + } else { + Ok(()) + } + } + _ => Err(( + AztecMacroError::CouldNotAssignStorageSlots { + secondary_message: Some( + "Function signature argument must be a literal string".to_string(), + ), + }, + file_id, + )), + }?; + + context + .def_interner + .update_expression(current_fn_signature_expression_id, |expr| { + *expr = HirExpression::Literal(HirLiteral::Str(fn_signature)) + }); + } + } + } + Ok(()) +} diff --git a/noir/noir-repo/aztec_macros/src/transforms/events.rs b/noir/noir-repo/aztec_macros/src/transforms/events.rs index 4f2b70453df..b77a5821b81 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/events.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/events.rs @@ -174,7 +174,7 @@ pub fn transform_events( crate_id: &CrateId, context: &mut HirContext, ) -> Result<(), (AztecMacroError, FileId)> { - for (_, struct_id) in collect_crate_structs(crate_id, context) { + for struct_id in collect_crate_structs(crate_id, context) { let attributes = context.def_interner.struct_attributes(&struct_id); if attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(event)")) { transform_event(struct_id, &mut context.def_interner)?; diff --git a/noir/noir-repo/aztec_macros/src/transforms/mod.rs b/noir/noir-repo/aztec_macros/src/transforms/mod.rs index 5a454c75148..2a6fef7647f 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/mod.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/mod.rs @@ -1,4 +1,5 @@ pub mod compute_note_hash_and_nullifier; +pub mod contract_interface; pub mod events; pub mod functions; pub mod note_interface; diff --git a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs index 0514155824e..4b72759a5db 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -528,12 +528,12 @@ fn generate_note_properties_fn_source( .join(", "); format!( " - pub fn properties() -> {}Properties {{ - {}Properties {{ - {} + pub fn properties() -> {0}Properties {{ + {0}Properties {{ + {1} }} }}", - note_type, note_type, note_property_selectors + note_type, note_property_selectors ) .to_string() } @@ -623,7 +623,7 @@ pub fn inject_note_exports( crate_id: &CrateId, context: &mut HirContext, ) -> Result<(), (AztecMacroError, FileId)> { - if let Some((module_id, file_id)) = get_contract_module_data(context, crate_id) { + if let Some((_, module_id, file_id)) = get_contract_module_data(context, crate_id) { let notes = fetch_notes(context); for (_, note) in notes { diff --git a/noir/noir-repo/aztec_macros/src/transforms/storage.rs b/noir/noir-repo/aztec_macros/src/transforms/storage.rs index 0bfb39cbc71..9135be32443 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/storage.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/storage.rs @@ -265,13 +265,13 @@ pub fn assign_storage_slots( context: &mut HirContext, ) -> Result<(), (AztecMacroError, FileId)> { let traits: Vec<_> = collect_traits(context); - if let Some((_, file_id)) = get_contract_module_data(context, crate_id) { + if let Some((_, _, file_id)) = get_contract_module_data(context, crate_id) { let maybe_storage_struct = - collect_crate_structs(crate_id, context).iter().find_map(|&(_, struct_id)| { - let r#struct = context.def_interner.get_struct(struct_id); - let attributes = context.def_interner.struct_attributes(&struct_id); + collect_crate_structs(crate_id, context).iter().find_map(|struct_id| { + let r#struct = context.def_interner.get_struct(*struct_id); + let attributes = context.def_interner.struct_attributes(struct_id); if attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(storage)")) - && r#struct.borrow().id.krate().is_root() + && r#struct.borrow().id.krate() == *crate_id { Some(r#struct) } else { @@ -290,7 +290,11 @@ pub fn assign_storage_slots( let expr = context.def_interner.expression(&statement.unwrap().expression); match expr { HirExpression::Constructor(hir_constructor_expression) => { - Some(hir_constructor_expression) + if hir_constructor_expression.r#type.borrow().id.krate() == *crate_id { + Some(hir_constructor_expression) + } else { + None + } } _ => None, } diff --git a/noir/noir-repo/aztec_macros/src/utils/constants.rs b/noir/noir-repo/aztec_macros/src/utils/constants.rs index 464cd10e2c7..848cca0477d 100644 --- a/noir/noir-repo/aztec_macros/src/utils/constants.rs +++ b/noir/noir-repo/aztec_macros/src/utils/constants.rs @@ -1,3 +1,4 @@ pub const FUNCTION_TREE_HEIGHT: u32 = 5; pub const MAX_CONTRACT_PRIVATE_FUNCTIONS: usize = 2_usize.pow(FUNCTION_TREE_HEIGHT); pub const SIGNATURE_PLACEHOLDER: &str = "SIGNATURE_PLACEHOLDER"; +pub const SELECTOR_PLACEHOLDER: &str = "SELECTOR_PLACEHOLDER"; diff --git a/noir/noir-repo/aztec_macros/src/utils/errors.rs b/noir/noir-repo/aztec_macros/src/utils/errors.rs index 52ee5587559..4c5411dfe0f 100644 --- a/noir/noir-repo/aztec_macros/src/utils/errors.rs +++ b/noir/noir-repo/aztec_macros/src/utils/errors.rs @@ -11,10 +11,12 @@ pub enum AztecMacroError { UnsupportedFunctionReturnType { span: Span, typ: UnresolvedTypeData }, UnsupportedStorageType { span: Option, typ: UnresolvedTypeData }, CouldNotAssignStorageSlots { secondary_message: Option }, + CouldNotImplementComputeNoteHashAndNullifier { secondary_message: Option }, CouldNotImplementNoteInterface { span: Option, secondary_message: Option }, MultipleStorageDefinitions { span: Option }, CouldNotExportStorageLayout { span: Option, secondary_message: Option }, CouldNotExportFunctionAbi { span: Option, secondary_message: Option }, + CouldNotGenerateContractInterface { secondary_message: Option }, EventError { span: Span, message: String }, UnsupportedAttributes { span: Span, secondary_message: Option }, } @@ -52,6 +54,11 @@ impl From for MacroError { secondary_message, span: None, }, + AztecMacroError::CouldNotImplementComputeNoteHashAndNullifier { secondary_message } => MacroError { + primary_message: "Could not implement compute_note_hash_and_nullifier automatically, please provide an implementation".to_string(), + secondary_message, + span: None, + }, AztecMacroError::CouldNotImplementNoteInterface { span, secondary_message } => MacroError { primary_message: "Could not implement automatic methods for note, please provide an implementation of the NoteInterface trait".to_string(), secondary_message, @@ -72,6 +79,11 @@ impl From for MacroError { secondary_message, span, }, + AztecMacroError::CouldNotGenerateContractInterface { secondary_message } => MacroError { + primary_message: "Could not generate contract interface".to_string(), + secondary_message, + span: None + }, AztecMacroError::EventError { span, message } => MacroError { primary_message: message, secondary_message: None, diff --git a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs index c4414e6419b..ae895d2075c 100644 --- a/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs +++ b/noir/noir-repo/aztec_macros/src/utils/hir_utils.rs @@ -7,43 +7,32 @@ use noirc_frontend::{ resolution::{path_resolver::StandardPathResolver, resolver::Resolver}, type_check::type_check_func, }, - macros_api::{FileId, HirContext, ModuleDefId, StructId}, + macros_api::{FileId, HirContext, MacroError, ModuleDefId, StructId}, node_interner::{FuncId, TraitId}, ItemVisibility, LetStatement, NoirFunction, Shared, Signedness, StructType, Type, }; use super::ast_utils::is_custom_attribute; -pub fn collect_crate_structs(crate_id: &CrateId, context: &HirContext) -> Vec<(String, StructId)> { +pub fn collect_crate_structs(crate_id: &CrateId, context: &HirContext) -> Vec { context .def_map(crate_id) - .expect("ICE: Missing crate in def_map") - .modules() - .iter() - .flat_map(|(_, module)| { - module.type_definitions().filter_map(move |typ| { - if let ModuleDefId::TypeId(struct_id) = typ { - let module_id = struct_id.module_id(); - let path = - context.fully_qualified_struct_path(context.root_crate_id(), struct_id); - let path = if path.contains("::") { - let prefix = if &module_id.krate == context.root_crate_id() { - "crate" + .map(|def_map| { + def_map + .modules() + .iter() + .flat_map(|(_, module)| { + module.type_definitions().filter_map(move |typ| { + if let ModuleDefId::TypeId(struct_id) = typ { + Some(struct_id) } else { - "dep" - }; - format!("{}::{}", prefix, path) - } else { - path - }; - - Some((path, struct_id)) - } else { - None - } - }) + None + } + }) + }) + .collect() }) - .collect() + .unwrap_or_default() } pub fn collect_crate_functions(crate_id: &CrateId, context: &HirContext) -> Vec { @@ -96,22 +85,48 @@ pub fn signature_of_type(typ: &Type) -> String { let fields = vecmap(types, signature_of_type); format!("({})", fields.join(",")) } + Type::String(len_typ) => { + if let Type::Constant(len) = **len_typ { + format!("str<{len}>") + } else { + unimplemented!( + "Cannot generate signature for string with length type {:?}", + len_typ + ) + } + } + Type::MutableReference(typ) => signature_of_type(typ), _ => unimplemented!("Cannot generate signature for type {:?}", typ), } } -// Fetches the name of all structs tagged as #[aztec(note)] in a given crate +// Fetches the name of all structs tagged as #[aztec(note)] in a given crate, avoiding +// contract dependencies that are just there for their interfaces. pub fn fetch_crate_notes( context: &HirContext, crate_id: &CrateId, ) -> Vec<(String, Shared)> { collect_crate_structs(crate_id, context) .iter() - .filter_map(|(path, struct_id)| { + .filter_map(|struct_id| { let r#struct = context.def_interner.get_struct(*struct_id); let attributes = context.def_interner.struct_attributes(struct_id); if attributes.iter().any(|attr| is_custom_attribute(attr, "aztec(note)")) { - Some((path.clone(), r#struct)) + let module_id = struct_id.module_id(); + + fully_qualified_note_path(context, *struct_id).map(|path| { + let path = if path.contains("::") { + let prefix = if &module_id.krate == context.root_crate_id() { + "crate" + } else { + "dep" + }; + format!("{}::{}", prefix, path) + } else { + path + }; + (path.clone(), r#struct) + }) } else { None } @@ -127,23 +142,24 @@ pub fn fetch_notes(context: &HirContext) -> Vec<(String, Shared)> { pub fn get_contract_module_data( context: &mut HirContext, crate_id: &CrateId, -) -> Option<(LocalModuleId, FileId)> { +) -> Option<(String, LocalModuleId, FileId)> { + let def_map = context.def_map(crate_id).expect("ICE: Missing crate in def_map"); // We first fetch modules in this crate which correspond to contracts, along with their file id. - let contract_module_file_ids: Vec<(LocalModuleId, FileId)> = context - .def_map(crate_id) - .expect("ICE: Missing crate in def_map") + let contract_module_file_ids: Vec<(String, LocalModuleId, FileId)> = def_map .modules() .iter() .filter(|(_, module)| module.is_contract) - .map(|(idx, module)| (LocalModuleId(idx), module.location.file)) + .map(|(idx, module)| { + (def_map.get_module_path(idx, module.parent), LocalModuleId(idx), module.location.file) + }) .collect(); - // If the current crate does not contain a contract module we simply skip it. More than 1 contract in a crate is forbidden by the compiler + // If the current crate does not contain a contract module we simply skip it. if contract_module_file_ids.is_empty() { return None; } - Some(contract_module_file_ids[0]) + Some(contract_module_file_ids[0].clone()) } pub fn inject_fn( @@ -153,7 +169,7 @@ pub fn inject_fn( location: Location, module_id: LocalModuleId, file_id: FileId, -) { +) -> Result<(), MacroError> { let func_id = context.def_interner.push_empty_fn(); context.def_interner.push_function( func_id, @@ -164,12 +180,11 @@ pub fn inject_fn( context.def_map_mut(crate_id).unwrap().modules_mut()[module_id.0] .declare_function(func.name_ident().clone(), ItemVisibility::Public, func_id) - .unwrap_or_else(|_| { - panic!( - "Failed to declare autogenerated {} function, likely due to a duplicate definition", - func.name() - ) - }); + .map_err(|err| MacroError { + primary_message: format!("Failed to declare autogenerated {} function", func.name()), + secondary_message: Some(format!("Duplicate definition found {}", err.0)), + span: None, + })?; let def_maps = &mut context.def_maps; @@ -183,7 +198,17 @@ pub fn inject_fn( context.def_interner.push_fn_meta(meta, func_id); context.def_interner.update_fn(func_id, hir_func); - type_check_func(&mut context.def_interner, func_id); + let errors = type_check_func(&mut context.def_interner, func_id); + + if !errors.is_empty() { + return Err(MacroError { + primary_message: "Failed to type check autogenerated function".to_owned(), + secondary_message: Some(errors.iter().map(|err| err.to_string()).collect::()), + span: None, + }); + } + + Ok(()) } pub fn inject_global( @@ -224,3 +249,63 @@ pub fn inject_global( let statement_id = context.def_interner.get_global(global_id).let_statement; context.def_interner.replace_statement(statement_id, hir_stmt); } + +pub fn fully_qualified_note_path(context: &HirContext, note_id: StructId) -> Option { + let module_id = note_id.module_id(); + let child_id = module_id.local_id.0; + let def_map = + context.def_map(&module_id.krate).expect("The local crate should be analyzed already"); + + let module = context.module(module_id); + + let module_path = def_map.get_module_path_with_separator(child_id, module.parent, "::"); + + if &module_id.krate == context.root_crate_id() { + Some(module_path) + } else { + find_non_contract_dependencies_bfs(context, context.root_crate_id(), &module_id.krate) + .map(|crates| crates.join("::") + "::" + &module_path) + } +} + +fn filter_contract_modules(context: &HirContext, crate_id: &CrateId) -> bool { + if let Some(def_map) = context.def_map(crate_id) { + !def_map.modules().iter().any(|(_, module)| module.is_contract) + } else { + true + } +} + +fn find_non_contract_dependencies_bfs( + context: &HirContext, + crate_id: &CrateId, + target_crate_id: &CrateId, +) -> Option> { + context.crate_graph[crate_id] + .dependencies + .iter() + .filter(|dep| filter_contract_modules(context, &dep.crate_id)) + .find_map(|dep| { + if &dep.crate_id == target_crate_id { + Some(vec![dep.name.to_string()]) + } else { + None + } + }) + .or_else(|| { + context.crate_graph[crate_id] + .dependencies + .iter() + .filter(|dep| filter_contract_modules(context, &dep.crate_id)) + .find_map(|dep| { + if let Some(mut path) = + find_non_contract_dependencies_bfs(context, &dep.crate_id, target_crate_id) + { + path.insert(0, dep.name.to_string()); + Some(path) + } else { + None + } + }) + }) +} diff --git a/noir/noir-repo/compiler/noirc_driver/src/contract.rs b/noir/noir-repo/compiler/noirc_driver/src/contract.rs index a33a9b809d3..d6c3dc6205d 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/contract.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/contract.rs @@ -53,7 +53,7 @@ pub struct ContractFunction { )] pub bytecode: Program, - pub debug: DebugInfo, + pub debug: Vec, /// Names of the functions in the program. These are used for more informative debugging and benchmarking. pub names: Vec, diff --git a/noir/noir-repo/compiler/noirc_driver/src/lib.rs b/noir/noir-repo/compiler/noirc_driver/src/lib.rs index 6fe44780484..8a554879e9f 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/lib.rs @@ -430,7 +430,8 @@ fn compile_contract_inner( } if errors.is_empty() { - let debug_infos: Vec<_> = functions.iter().map(|function| function.debug.clone()).collect(); + let debug_infos: Vec<_> = + functions.iter().flat_map(|function| function.debug.clone()).collect(); let file_map = filter_relevant_files(&debug_infos, &context.file_manager); let out_structs = contract @@ -547,13 +548,8 @@ pub fn compile_no_check( Ok(CompiledProgram { hash, - // TODO(https://github.com/noir-lang/noir/issues/4428) program, - // TODO(https://github.com/noir-lang/noir/issues/4428) - // Debug info is only relevant for errors at execution time which is not yet supported - // The CompileProgram `debug` field is used in multiple places and is better - // left to be updated once execution of multiple ACIR functions is enabled - debug: debug[0].clone(), + debug, abi, file_map, noir_version: NOIR_ARTIFACT_VERSION_STRING.to_string(), diff --git a/noir/noir-repo/compiler/noirc_driver/src/program.rs b/noir/noir-repo/compiler/noirc_driver/src/program.rs index 9ffd2d70dda..ed7ddb29f59 100644 --- a/noir/noir-repo/compiler/noirc_driver/src/program.rs +++ b/noir/noir-repo/compiler/noirc_driver/src/program.rs @@ -24,7 +24,7 @@ pub struct CompiledProgram { )] pub program: Program, pub abi: noirc_abi::Abi, - pub debug: DebugInfo, + pub debug: Vec, pub file_map: BTreeMap, pub warnings: Vec, /// Names of the functions in the program. These are used for more informative debugging and benchmarking. diff --git a/noir/noir-repo/compiler/noirc_errors/src/debug_info.rs b/noir/noir-repo/compiler/noirc_errors/src/debug_info.rs index 09117bdc3b7..54e2521e413 100644 --- a/noir/noir-repo/compiler/noirc_errors/src/debug_info.rs +++ b/noir/noir-repo/compiler/noirc_errors/src/debug_info.rs @@ -46,6 +46,49 @@ pub type DebugVariables = BTreeMap; pub type DebugFunctions = BTreeMap; pub type DebugTypes = BTreeMap; +#[derive(Default, Debug, Clone, Deserialize, Serialize)] +pub struct ProgramDebugInfo { + pub debug_infos: Vec, +} + +impl ProgramDebugInfo { + pub fn serialize_compressed_base64_json( + debug_info: &ProgramDebugInfo, + s: S, + ) -> Result + where + S: Serializer, + { + let json_str = serde_json::to_string(debug_info).map_err(S::Error::custom)?; + + let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default()); + encoder.write_all(json_str.as_bytes()).map_err(S::Error::custom)?; + let compressed_data = encoder.finish().map_err(S::Error::custom)?; + + let encoded_b64 = base64::prelude::BASE64_STANDARD.encode(compressed_data); + s.serialize_str(&encoded_b64) + } + + pub fn deserialize_compressed_base64_json<'de, D>( + deserializer: D, + ) -> Result + where + D: Deserializer<'de>, + { + let encoded_b64: String = Deserialize::deserialize(deserializer)?; + + let compressed_data = + base64::prelude::BASE64_STANDARD.decode(encoded_b64).map_err(D::Error::custom)?; + + let mut decoder = DeflateDecoder::new(&compressed_data[..]); + let mut decompressed_data = Vec::new(); + decoder.read_to_end(&mut decompressed_data).map_err(D::Error::custom)?; + + let json_str = String::from_utf8(decompressed_data).map_err(D::Error::custom)?; + serde_json::from_str(&json_str).map_err(D::Error::custom) + } +} + #[serde_as] #[derive(Default, Debug, Clone, Deserialize, Serialize)] pub struct DebugInfo { @@ -130,40 +173,4 @@ impl DebugInfo { counted_opcodes } - - pub fn serialize_compressed_base64_json( - debug_info: &DebugInfo, - s: S, - ) -> Result - where - S: Serializer, - { - let json_str = serde_json::to_string(debug_info).map_err(S::Error::custom)?; - - let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default()); - encoder.write_all(json_str.as_bytes()).map_err(S::Error::custom)?; - let compressed_data = encoder.finish().map_err(S::Error::custom)?; - - let encoded_b64 = base64::prelude::BASE64_STANDARD.encode(compressed_data); - s.serialize_str(&encoded_b64) - } - - pub fn deserialize_compressed_base64_json<'de, D>( - deserializer: D, - ) -> Result - where - D: Deserializer<'de>, - { - let encoded_b64: String = Deserialize::deserialize(deserializer)?; - - let compressed_data = - base64::prelude::BASE64_STANDARD.decode(encoded_b64).map_err(D::Error::custom)?; - - let mut decoder = DeflateDecoder::new(&compressed_data[..]); - let mut decompressed_data = Vec::new(); - decoder.read_to_end(&mut decompressed_data).map_err(D::Error::custom)?; - - let json_str = String::from_utf8(decompressed_data).map_err(D::Error::custom)?; - serde_json::from_str(&json_str).map_err(D::Error::custom) - } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs index 36b5f8793cb..ee047903743 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_black_box.rs @@ -1,8 +1,11 @@ -use acvm::acir::{brillig::BlackBoxOp, BlackBoxFunc}; +use acvm::{ + acir::{brillig::BlackBoxOp, BlackBoxFunc}, + FieldElement, +}; use crate::brillig::brillig_ir::{ brillig_variable::{BrilligVariable, BrilligVector, SingleAddrVariable}, - BrilligContext, + BrilligBinaryOp, BrilligContext, }; /// Transforms SSA's black box function calls into the corresponding brillig instructions @@ -235,10 +238,17 @@ pub(crate) fn convert_black_box_call( ), BlackBoxFunc::BigIntAdd => { if let ( - [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(rhs)], - [BrilligVariable::SingleAddr(output)], + [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(lhs_modulus), BrilligVariable::SingleAddr(rhs), BrilligVariable::SingleAddr(rhs_modulus)], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { + prepare_bigint_output( + brillig_context, + lhs_modulus, + rhs_modulus, + output, + modulus_id, + ); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntAdd { lhs: lhs.address, rhs: rhs.address, @@ -246,16 +256,23 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: BigIntAdd expects two register arguments and one result register" + "ICE: BigIntAdd expects four register arguments and two result registers" ) } } BlackBoxFunc::BigIntSub => { if let ( - [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(rhs)], - [BrilligVariable::SingleAddr(output)], + [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(lhs_modulus), BrilligVariable::SingleAddr(rhs), BrilligVariable::SingleAddr(rhs_modulus)], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { + prepare_bigint_output( + brillig_context, + lhs_modulus, + rhs_modulus, + output, + modulus_id, + ); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntSub { lhs: lhs.address, rhs: rhs.address, @@ -263,16 +280,23 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: BigIntSub expects two register arguments and one result register" + "ICE: BigIntSub expects four register arguments and two result registers" ) } } BlackBoxFunc::BigIntMul => { if let ( - [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(rhs)], - [BrilligVariable::SingleAddr(output)], + [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(lhs_modulus), BrilligVariable::SingleAddr(rhs), BrilligVariable::SingleAddr(rhs_modulus)], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { + prepare_bigint_output( + brillig_context, + lhs_modulus, + rhs_modulus, + output, + modulus_id, + ); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntMul { lhs: lhs.address, rhs: rhs.address, @@ -280,16 +304,23 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: BigIntMul expects two register arguments and one result register" + "ICE: BigIntMul expects four register arguments and two result registers" ) } } BlackBoxFunc::BigIntDiv => { if let ( - [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(rhs)], - [BrilligVariable::SingleAddr(output)], + [BrilligVariable::SingleAddr(lhs), BrilligVariable::SingleAddr(lhs_modulus), BrilligVariable::SingleAddr(rhs), BrilligVariable::SingleAddr(rhs_modulus)], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(modulus_id)], ) = (function_arguments, function_results) { + prepare_bigint_output( + brillig_context, + lhs_modulus, + rhs_modulus, + output, + modulus_id, + ); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntDiv { lhs: lhs.address, rhs: rhs.address, @@ -297,16 +328,20 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: BigIntDiv expects two register arguments and one result register" + "ICE: BigIntDiv expects four register arguments and two result registers" ) } } BlackBoxFunc::BigIntFromLeBytes => { - if let ([inputs, modulus], [BrilligVariable::SingleAddr(output)]) = - (function_arguments, function_results) + if let ( + [inputs, modulus], + [BrilligVariable::SingleAddr(output), BrilligVariable::SingleAddr(_modulus_id)], + ) = (function_arguments, function_results) { let inputs_vector = convert_array_or_vector(brillig_context, inputs, bb_func); let modulus_vector = convert_array_or_vector(brillig_context, modulus, bb_func); + let output_id = brillig_context.get_new_bigint_id(); + brillig_context.const_instruction(*output, FieldElement::from(output_id as u128)); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntFromLeBytes { inputs: inputs_vector.to_heap_vector(), modulus: modulus_vector.to_heap_vector(), @@ -314,23 +349,24 @@ pub(crate) fn convert_black_box_call( }); } else { unreachable!( - "ICE: BigIntFromLeBytes expects two register arguments and one result register" + "ICE: BigIntFromLeBytes expects a register and an array as arguments and two result registers" ) } } BlackBoxFunc::BigIntToLeBytes => { if let ( - [BrilligVariable::SingleAddr(input)], - [BrilligVariable::BrilligVector(result_vector)], + [BrilligVariable::SingleAddr(input), BrilligVariable::SingleAddr(_modulus)], + [result_array], ) = (function_arguments, function_results) { + let output = convert_array_or_vector(brillig_context, result_array, bb_func); brillig_context.black_box_op_instruction(BlackBoxOp::BigIntToLeBytes { input: input.address, - output: result_vector.to_heap_vector(), + output: output.to_heap_vector(), }); } else { unreachable!( - "ICE: BigIntToLeBytes expects one register argument and one array result" + "ICE: BigIntToLeBytes expects two register arguments and one array result" ) } } @@ -383,3 +419,30 @@ fn convert_array_or_vector( ), } } + +fn prepare_bigint_output( + brillig_context: &mut BrilligContext, + lhs_modulus: &SingleAddrVariable, + rhs_modulus: &SingleAddrVariable, + output: &SingleAddrVariable, + modulus_id: &SingleAddrVariable, +) { + // Check moduli + let condition = brillig_context.allocate_register(); + let condition_adr = SingleAddrVariable { address: condition, bit_size: 1 }; + brillig_context.binary_instruction( + *lhs_modulus, + *rhs_modulus, + condition_adr, + BrilligBinaryOp::Equals, + ); + brillig_context.codegen_constrain( + condition_adr, + Some("moduli should be identical in BigInt operation".to_string()), + ); + brillig_context.deallocate_register(condition); + // Set output id + let output_id = brillig_context.get_new_bigint_id(); + brillig_context.const_instruction(*output, FieldElement::from(output_id as u128)); + brillig_context.mov_instruction(modulus_id.address, lhs_modulus.address); +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index 369d8e78cda..22407fc5695 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -1785,7 +1785,7 @@ pub(crate) fn type_of_binary_operation(lhs_type: &Type, rhs_type: &Type) -> Type (Type::Numeric(lhs_type), Type::Numeric(rhs_type)) => { assert_eq!( lhs_type, rhs_type, - "lhs and rhs types in a binary operation are always the same" + "lhs and rhs types in a binary operation are always the same but got {lhs_type} and {rhs_type}" ); Type::Numeric(*lhs_type) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index fdb03abe59f..7e37e1da434 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -86,6 +86,8 @@ pub(crate) struct BrilligContext { next_section: usize, /// IR printer debug_show: DebugShow, + /// Counter for generating bigint ids in unconstrained functions + bigint_new_id: u32, } impl BrilligContext { @@ -98,9 +100,15 @@ impl BrilligContext { section_label: 0, next_section: 1, debug_show: DebugShow::new(enable_debug_trace), + bigint_new_id: 0, } } + pub(crate) fn get_new_bigint_id(&mut self) -> u32 { + let result = self.bigint_new_id; + self.bigint_new_id += 1; + result + } /// Adds a brillig instruction to the brillig byte code fn push_opcode(&mut self, opcode: BrilligOpcode) { self.obj.push_opcode(opcode); @@ -140,7 +148,7 @@ pub(crate) mod tests { &self, _public_key_x: &FieldElement, _public_key_y: &FieldElement, - _signature: &[u8], + _signature: &[u8; 64], _message: &[u8], ) -> Result { Ok(true) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 8ce15ba4e73..8a4f469f5c9 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -4,7 +4,7 @@ use std::collections::{BTreeMap, HashMap}; use crate::ssa::ir::dfg::CallStack; /// Represents a parameter or a return value of an entry point function. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] pub(crate) enum BrilligParameter { /// A single address parameter or return value. Holds the bit size of the parameter. SingleAddr(u32), @@ -17,7 +17,7 @@ pub(crate) enum BrilligParameter { /// The result of compiling and linking brillig artifacts. /// This is ready to run bytecode with attached metadata. -#[derive(Debug)] +#[derive(Debug, Default)] pub(crate) struct GeneratedBrillig { pub(crate) byte_code: Vec, pub(crate) locations: BTreeMap, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index fe3c5e0bb9c..88cf987325d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -23,6 +23,7 @@ impl BrilligContext { section_label: 0, next_section: 1, debug_show: DebugShow::new(false), + bigint_new_id: 0, }; context.codegen_entry_point(&arguments, &return_parameters); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index ce4a9bbe9f1..760340f1a88 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -14,7 +14,9 @@ use crate::{ errors::{RuntimeError, SsaReport}, }; use acvm::acir::{ - circuit::{Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs}, + circuit::{ + brillig::BrilligBytecode, Circuit, ExpressionWidth, Program as AcirProgram, PublicInputs, + }, native_types::Witness, }; @@ -35,14 +37,16 @@ pub mod ssa_gen; /// Optimize the given program by converting it into SSA /// form and performing optimizations there. When finished, -/// convert the final SSA into ACIR and return it. +/// convert the final SSA into an ACIR program and return it. +/// An ACIR program is made up of both ACIR functions +/// and Brillig functions for unconstrained execution. pub(crate) fn optimize_into_acir( program: Program, print_passes: bool, print_brillig_trace: bool, force_brillig_output: bool, print_timings: bool, -) -> Result, RuntimeError> { +) -> Result<(Vec, Vec), RuntimeError> { let abi_distinctness = program.return_distinctness; let ssa_gen_span = span!(Level::TRACE, "ssa_generation"); @@ -99,6 +103,18 @@ pub struct SsaProgramArtifact { } impl SsaProgramArtifact { + fn new(unconstrained_functions: Vec) -> Self { + let program = AcirProgram { functions: Vec::default(), unconstrained_functions }; + Self { + program, + debug: Vec::default(), + warnings: Vec::default(), + main_input_witnesses: Vec::default(), + main_return_witnesses: Vec::default(), + names: Vec::default(), + } + } + fn add_circuit(&mut self, mut circuit_artifact: SsaCircuitArtifact, is_main: bool) { self.program.functions.push(circuit_artifact.circuit); self.debug.push(circuit_artifact.debug_info); @@ -130,7 +146,7 @@ pub fn create_program( let func_sigs = program.function_signatures.clone(); let recursive = program.recursive; - let generated_acirs = optimize_into_acir( + let (generated_acirs, generated_brillig) = optimize_into_acir( program, enable_ssa_logging, enable_brillig_logging, @@ -143,7 +159,7 @@ pub fn create_program( "The generated ACIRs should match the supplied function signatures" ); - let mut program_artifact = SsaProgramArtifact::default(); + let mut program_artifact = SsaProgramArtifact::new(generated_brillig); // For setting up the ABI we need separately specify main's input and return witnesses let mut is_main = true; for (acir, func_sig) in generated_acirs.into_iter().zip(func_sigs) { diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 775571f4a41..b94e02e5119 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -1261,7 +1261,8 @@ impl AcirContext { let modulus = self.big_int_ctx.modulus(bigint.modulus_id()); let bytes_len = ((modulus - BigUint::from(1_u32)).bits() - 1) / 8 + 1; output_count = bytes_len as usize; - (field_inputs, vec![FieldElement::from(bytes_len as u128)]) + assert!(bytes_len == 32); + (field_inputs, vec![]) } BlackBoxFunc::BigIntFromLeBytes => { let invalid_input = "ICE - bigint operation requires 2 inputs"; @@ -1463,6 +1464,7 @@ impl AcirContext { id } + // TODO: Delete this method once we remove the `Brillig` opcode pub(crate) fn brillig( &mut self, predicate: AcirVar, @@ -1553,6 +1555,105 @@ impl AcirContext { Ok(outputs_var) } + #[allow(clippy::too_many_arguments)] + pub(crate) fn brillig_call( + &mut self, + predicate: AcirVar, + generated_brillig: &GeneratedBrillig, + inputs: Vec, + outputs: Vec, + attempt_execution: bool, + unsafe_return_values: bool, + brillig_function_index: u32, + ) -> Result, RuntimeError> { + let brillig_inputs = try_vecmap(inputs, |i| -> Result<_, InternalError> { + match i { + AcirValue::Var(var, _) => Ok(BrilligInputs::Single(self.var_to_expression(var)?)), + AcirValue::Array(vars) => { + let mut var_expressions: Vec = Vec::new(); + for var in vars { + self.brillig_array_input(&mut var_expressions, var)?; + } + Ok(BrilligInputs::Array(var_expressions)) + } + AcirValue::DynamicArray(AcirDynamicArray { block_id, .. }) => { + Ok(BrilligInputs::MemoryArray(block_id)) + } + } + })?; + + // Optimistically try executing the brillig now, if we can complete execution they just return the results. + // This is a temporary measure pending SSA optimizations being applied to Brillig which would remove constant-input opcodes (See #2066) + // + // We do _not_ want to do this in the situation where the `main` function is unconstrained, as if execution succeeds + // the entire program will be replaced with witness constraints to its outputs. + if attempt_execution { + if let Some(brillig_outputs) = + self.execute_brillig(&generated_brillig.byte_code, &brillig_inputs, &outputs) + { + return Ok(brillig_outputs); + } + } + + // Otherwise we must generate ACIR for it and execute at runtime. + let mut brillig_outputs = Vec::new(); + let outputs_var = vecmap(outputs, |output| match output { + AcirType::NumericType(_) => { + let witness_index = self.acir_ir.next_witness_index(); + brillig_outputs.push(BrilligOutputs::Simple(witness_index)); + let var = self.add_data(AcirVarData::Witness(witness_index)); + AcirValue::Var(var, output.clone()) + } + AcirType::Array(element_types, size) => { + let (acir_value, witnesses) = self.brillig_array_output(&element_types, size); + brillig_outputs.push(BrilligOutputs::Array(witnesses)); + acir_value + } + }); + let predicate = self.var_to_expression(predicate)?; + + self.acir_ir.brillig_call( + Some(predicate), + generated_brillig, + brillig_inputs, + brillig_outputs, + brillig_function_index, + ); + + fn range_constraint_value( + context: &mut AcirContext, + value: &AcirValue, + ) -> Result<(), RuntimeError> { + match value { + AcirValue::Var(var, typ) => { + let numeric_type = match typ { + AcirType::NumericType(numeric_type) => numeric_type, + _ => unreachable!("`AcirValue::Var` may only hold primitive values"), + }; + context.range_constrain_var(*var, numeric_type, None)?; + } + AcirValue::Array(values) => { + for value in values { + range_constraint_value(context, value)?; + } + } + AcirValue::DynamicArray(_) => { + unreachable!("Brillig opcodes cannot return dynamic arrays") + } + } + Ok(()) + } + + // This is a hack to ensure that if we're compiling a brillig entrypoint function then + // we don't also add a number of range constraints. + if !unsafe_return_values { + for output_var in &outputs_var { + range_constraint_value(self, output_var)?; + } + } + Ok(outputs_var) + } + fn brillig_array_input( &mut self, var_expressions: &mut Vec, diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index e16eb2172be..999ff2ddb5d 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -589,6 +589,7 @@ impl GeneratedAcir { Ok(()) } + // TODO: Delete this method once we remove the `Brillig` opcode pub(crate) fn brillig( &mut self, predicate: Option, @@ -617,6 +618,37 @@ impl GeneratedAcir { } } + pub(crate) fn brillig_call( + &mut self, + predicate: Option, + generated_brillig: &GeneratedBrillig, + inputs: Vec, + outputs: Vec, + brillig_function_index: u32, + ) { + let opcode = + AcirOpcode::BrilligCall { id: brillig_function_index, inputs, outputs, predicate }; + self.push_opcode(opcode); + for (brillig_index, call_stack) in generated_brillig.locations.iter() { + self.locations.insert( + OpcodeLocation::Brillig { + acir_index: self.opcodes.len() - 1, + brillig_index: *brillig_index, + }, + call_stack.clone(), + ); + } + for (brillig_index, message) in generated_brillig.assert_messages.iter() { + self.assert_messages.insert( + OpcodeLocation::Brillig { + acir_index: self.opcodes.len() - 1, + brillig_index: *brillig_index, + }, + message.clone(), + ); + } + } + pub(crate) fn last_acir_opcode_location(&self) -> OpcodeLocation { OpcodeLocation::Acir(self.opcodes.len() - 1) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 76cc8acf878..02b381d79fc 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1,12 +1,13 @@ //! This file holds the pass to convert from Noir's SSA IR to ACIR. mod acir_ir; -use std::collections::HashSet; +use std::collections::{BTreeMap, HashSet}; use std::fmt::Debug; use self::acir_ir::acir_variable::{AcirContext, AcirType, AcirVar}; use super::function_builder::data_bus::DataBus; use super::ir::dfg::CallStack; +use super::ir::function::FunctionId; use super::ir::instruction::{ConstrainError, UserDefinedConstrainError}; use super::{ ir::{ @@ -28,6 +29,7 @@ use crate::errors::{InternalError, InternalWarning, RuntimeError, SsaReport}; use crate::ssa::ir::function::InlineType; pub(crate) use acir_ir::generated_acir::GeneratedAcir; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::native_types::Witness; use acvm::acir::BlackBoxFunc; use acvm::{ @@ -39,9 +41,54 @@ use im::Vector; use iter_extended::{try_vecmap, vecmap}; use noirc_frontend::Distinctness; +#[derive(Default)] +struct SharedContext { + /// Final list of Brillig functions which will be part of the final program + /// This is shared across `Context` structs as we want one list of Brillig + /// functions across all ACIR artifacts + generated_brillig: Vec, + + /// Maps SSA function index -> Final generated Brillig artifact index. + /// There can be Brillig functions specified in SSA which do not act as + /// entry points in ACIR (e.g. only called by other Brillig functions) + /// This mapping is necessary to use the correct function pointer for a Brillig call. + /// This uses the brillig parameters in the map since using slices with different lengths + /// needs to create different brillig entrypoints + brillig_generated_func_pointers: BTreeMap<(FunctionId, Vec), u32>, +} + +impl SharedContext { + fn generated_brillig_pointer( + &self, + func_id: FunctionId, + arguments: Vec, + ) -> Option<&u32> { + self.brillig_generated_func_pointers.get(&(func_id, arguments)) + } + + fn generated_brillig(&self, func_pointer: usize) -> &GeneratedBrillig { + &self.generated_brillig[func_pointer] + } + + fn insert_generated_brillig( + &mut self, + func_id: FunctionId, + arguments: Vec, + generated_pointer: u32, + code: GeneratedBrillig, + ) { + self.brillig_generated_func_pointers.insert((func_id, arguments), generated_pointer); + self.generated_brillig.push(code); + } + + fn new_generated_pointer(&self) -> u32 { + self.generated_brillig.len() as u32 + } +} + /// Context struct for the acir generation pass. /// May be similar to the Evaluator struct in the current SSA IR. -struct Context { +struct Context<'a> { /// Maps SSA values to `AcirVar`. /// /// This is needed so that we only create a single @@ -91,6 +138,9 @@ struct Context { max_block_id: u32, data_bus: DataBus, + + /// Contains state that is generated and also used across ACIR functions + shared_context: &'a mut SharedContext, } #[derive(Clone)] @@ -181,11 +231,12 @@ impl Ssa { self, brillig: &Brillig, abi_distinctness: Distinctness, - ) -> Result, RuntimeError> { + ) -> Result<(Vec, Vec), RuntimeError> { let mut acirs = Vec::new(); // TODO: can we parallelise this? + let mut shared_context = SharedContext::default(); for function in self.functions.values() { - let context = Context::new(); + let context = Context::new(&mut shared_context); if let Some(mut generated_acir) = context.convert_ssa_function(&self, function, brillig)? { @@ -194,6 +245,10 @@ impl Ssa { } } + let brillig = vecmap(shared_context.generated_brillig, |brillig| BrilligBytecode { + bytecode: brillig.byte_code, + }); + // TODO: check whether doing this for a single circuit's return witnesses is correct. // We probably need it for all foldable circuits, as any circuit being folded is essentially an entry point. However, I do not know how that // plays a part when we potentially want not inlined functions normally as part of the compiler. @@ -215,15 +270,15 @@ impl Ssa { .collect(); main_func_acir.return_witnesses = distinct_return_witness; - Ok(acirs) } - Distinctness::DuplicationAllowed => Ok(acirs), + Distinctness::DuplicationAllowed => {} } + Ok((acirs, brillig)) } } -impl Context { - fn new() -> Context { +impl<'a> Context<'a> { + fn new(shared_context: &'a mut SharedContext) -> Context<'a> { let mut acir_context = AcirContext::default(); let current_side_effects_enabled_var = acir_context.add_constant(FieldElement::one()); @@ -237,6 +292,7 @@ impl Context { internal_mem_block_lengths: HashMap::default(), max_block_id: 0, data_bus: DataBus::default(), + shared_context, } } @@ -307,18 +363,22 @@ impl Context { let outputs: Vec = vecmap(main_func.returns(), |result_id| dfg.type_of_value(*result_id).into()); - let code = self.gen_brillig_for(main_func, arguments, brillig)?; + let code = self.gen_brillig_for(main_func, arguments.clone(), brillig)?; // We specifically do not attempt execution of the brillig code being generated as this can result in it being // replaced with constraints on witnesses to the program outputs. - let output_values = self.acir_context.brillig( + let output_values = self.acir_context.brillig_call( self.current_side_effects_enabled_var, - code, + &code, inputs, outputs, false, true, + // We are guaranteed to have a Brillig function pointer of `0` as main itself is marked as unconstrained + 0, )?; + self.shared_context.insert_generated_brillig(main_func.id(), arguments, 0, code); + let output_vars: Vec<_> = output_values .iter() .flat_map(|value| value.clone().flatten()) @@ -576,12 +636,12 @@ impl Context { sum + dfg.try_get_array_length(*result_id).unwrap_or(1) }); - let acir_program_id = ssa - .id_to_index + let acir_function_id = ssa + .entry_point_to_generated_index .get(id) .expect("ICE: should have an associated final index"); let output_vars = self.acir_context.call_acir_function( - *acir_program_id, + *acir_function_id, inputs, output_count, self.current_side_effects_enabled_var, @@ -603,24 +663,53 @@ impl Context { ); } } - let inputs = vecmap(arguments, |arg| self.convert_value(*arg, dfg)); let arguments = self.gen_brillig_parameters(arguments, dfg); - let code = self.gen_brillig_for(func, arguments, brillig)?; - let outputs: Vec = vecmap(result_ids, |result_id| { dfg.type_of_value(*result_id).into() }); - let output_values = self.acir_context.brillig( - self.current_side_effects_enabled_var, - code, - inputs, - outputs, - true, - false, - )?; + // Check whether we have already generated Brillig for this function + // If we have, re-use the generated code to set-up the Brillig call. + let output_values = if let Some(generated_pointer) = self + .shared_context + .generated_brillig_pointer(*id, arguments.clone()) + { + let code = self + .shared_context + .generated_brillig(*generated_pointer as usize); + self.acir_context.brillig_call( + self.current_side_effects_enabled_var, + code, + inputs, + outputs, + true, + false, + *generated_pointer, + )? + } else { + let code = + self.gen_brillig_for(func, arguments.clone(), brillig)?; + let generated_pointer = + self.shared_context.new_generated_pointer(); + let output_values = self.acir_context.brillig_call( + self.current_side_effects_enabled_var, + &code, + inputs, + outputs, + true, + false, + generated_pointer, + )?; + self.shared_context.insert_generated_brillig( + *id, + arguments, + generated_pointer, + code, + ); + output_values + }; // Compiler sanity check assert_eq!(result_ids.len(), output_values.len(), "ICE: The number of Brillig output values should match the result ids in SSA"); @@ -2447,19 +2536,27 @@ mod test { }, }; - fn build_basic_foo_with_return(builder: &mut FunctionBuilder, foo_id: FunctionId) { - // acir(fold) fn foo f1 { + fn build_basic_foo_with_return( + builder: &mut FunctionBuilder, + foo_id: FunctionId, + is_brillig_func: bool, + ) { + // fn foo f1 { // b0(v0: Field, v1: Field): // v2 = eq v0, v1 // constrain v2 == u1 0 // return v0 // } - builder.new_function("foo".into(), foo_id, InlineType::Fold); + if is_brillig_func { + builder.new_brillig_function("foo".into(), foo_id); + } else { + builder.new_function("foo".into(), foo_id, InlineType::Fold); + } let foo_v0 = builder.add_parameter(Type::field()); let foo_v1 = builder.add_parameter(Type::field()); let foo_equality_check = builder.insert_binary(foo_v0, BinaryOp::Eq, foo_v1); - let zero = builder.field_constant(0u128); + let zero = builder.numeric_constant(0u128, Type::unsigned(1)); builder.insert_constrain(foo_equality_check, zero, None); builder.terminate_with_return(vec![foo_v0]); } @@ -2493,11 +2590,11 @@ mod test { builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); builder.terminate_with_return(vec![]); - build_basic_foo_with_return(&mut builder, foo_id); + build_basic_foo_with_return(&mut builder, foo_id, false); let ssa = builder.finish(); - let acir_functions = ssa + let (acir_functions, _) = ssa .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); // Expected result: @@ -2589,11 +2686,11 @@ mod test { builder.insert_constrain(main_call1_results[0], main_call2_results[0], None); builder.terminate_with_return(vec![]); - build_basic_foo_with_return(&mut builder, foo_id); + build_basic_foo_with_return(&mut builder, foo_id, false); let ssa = builder.finish(); - let acir_functions = ssa + let (acir_functions, _) = ssa .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); // The expected result should look very similar to the abvoe test expect that the input witnesses of the `Call` @@ -2680,11 +2777,11 @@ mod test { .to_vec(); builder.terminate_with_return(vec![foo_call[0]]); - build_basic_foo_with_return(&mut builder, foo_id); + build_basic_foo_with_return(&mut builder, foo_id, false); let ssa = builder.finish(); - let acir_functions = ssa + let (acir_functions, _) = ssa .into_acir(&Brillig::default(), noirc_frontend::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); @@ -2744,4 +2841,82 @@ mod test { _ => panic!("Expected only Call opcode"), } } + + // Test that given multiple calls to the same brillig function we generate only one bytecode + // and the appropriate Brillig call opcodes are generated + #[test] + fn multiple_brillig_calls_one_bytecode() { + // acir(inline) fn main f0 { + // b0(v0: Field, v1: Field): + // v3 = call f1(v0, v1) + // v4 = call f1(v0, v1) + // v5 = call f1(v0, v1) + // v6 = call f1(v0, v1) + // return + // } + // brillig fn foo f1 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + // brillig fn foo f2 { + // b0(v0: Field, v1: Field): + // v2 = eq v0, v1 + // constrain v2 == u1 0 + // return v0 + // } + let foo_id = Id::test_new(0); + let mut builder = FunctionBuilder::new("main".into(), foo_id); + let main_v0 = builder.add_parameter(Type::field()); + let main_v1 = builder.add_parameter(Type::field()); + + let foo_id = Id::test_new(1); + let foo = builder.import_function(foo_id); + let bar_id = Id::test_new(2); + let bar = builder.import_function(bar_id); + + // Insert multiple calls to the same Brillig function + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + // Interleave a call to a separate Brillig function to make sure that we can call multiple separate Brillig functions + builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(foo, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.insert_call(bar, vec![main_v0, main_v1], vec![Type::field()]).to_vec(); + builder.terminate_with_return(vec![]); + + build_basic_foo_with_return(&mut builder, foo_id, true); + build_basic_foo_with_return(&mut builder, bar_id, true); + + let ssa = builder.finish(); + let brillig = ssa.to_brillig(false); + println!("{}", ssa); + + let (acir_functions, brillig_functions) = ssa + .into_acir(&brillig, noirc_frontend::Distinctness::Distinct) + .expect("Should compile manually written SSA into ACIR"); + + assert_eq!(acir_functions.len(), 1, "Should only have a `main` ACIR function"); + assert_eq!( + brillig_functions.len(), + 2, + "Should only have generated a single Brillig function" + ); + + let main_acir = &acir_functions[0]; + let main_opcodes = main_acir.opcodes(); + assert_eq!(main_opcodes.len(), 6, "Should have four calls to f1 and two calls to f2"); + + // We should only have `BrilligCall` opcodes in `main` + for (i, opcode) in main_opcodes.iter().enumerate() { + match opcode { + Opcode::BrilligCall { id, .. } => { + let expected_id = if i == 3 || i == 5 { 1 } else { 0 }; + assert_eq!(*id, expected_id, "Expected an id of {expected_id} but got {id}"); + } + _ => panic!("Expected only Brillig call opcode"), + } + } + } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 59ce4e4f754..2a4b5276547 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -243,6 +243,7 @@ impl<'a> FunctionContext<'a> { Ok(Tree::Branch(vec![string, field_count.into(), fields])) } + ast::Literal::Unit => Ok(Self::unit_value()), } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs index 9995c031145..b05a2cbc741 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/program.rs @@ -3,7 +3,7 @@ use std::{collections::BTreeMap, fmt::Display}; use iter_extended::btree_map; use crate::ssa::ir::{ - function::{Function, FunctionId}, + function::{Function, FunctionId, RuntimeType}, map::AtomicCounter, }; @@ -12,7 +12,11 @@ pub(crate) struct Ssa { pub(crate) functions: BTreeMap, pub(crate) main_id: FunctionId, pub(crate) next_id: AtomicCounter, - pub(crate) id_to_index: BTreeMap, + /// Maps SSA entry point function ID -> Final generated ACIR artifact index. + /// There can be functions specified in SSA which do not act as ACIR entry points. + /// This mapping is necessary to use the correct function pointer for an ACIR call, + /// as the final program artifact will be a list of only entry point functions. + pub(crate) entry_point_to_generated_index: BTreeMap, } impl Ssa { @@ -27,9 +31,26 @@ impl Ssa { (f.id(), f) }); - let id_to_index = btree_map(functions.iter().enumerate(), |(i, (id, _))| (*id, i as u32)); + let entry_point_to_generated_index = btree_map( + functions + .iter() + .filter(|(_, func)| { + let runtime = func.runtime(); + match func.runtime() { + RuntimeType::Acir(_) => runtime.is_entry_point() || func.id() == main_id, + RuntimeType::Brillig => false, + } + }) + .enumerate(), + |(i, (id, _))| (*id, i as u32), + ); - Self { functions, main_id, next_id: AtomicCounter::starting_after(max_id), id_to_index } + Self { + functions, + main_id, + next_id: AtomicCounter::starting_after(max_id), + entry_point_to_generated_index, + } } /// Returns the entry-point function of the program diff --git a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml index 03b92e15032..e39ab2fe106 100644 --- a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml @@ -24,9 +24,16 @@ small-ord-set = "0.1.3" regex = "1.9.1" tracing.workspace = true petgraph = "0.6" +lalrpop-util = { version = "0.20.2", features = ["lexer"] } [dev-dependencies] base64.workspace = true strum = "0.24" strum_macros = "0.24" tempfile.workspace = true + +[build-dependencies] +lalrpop = "0.20.2" + +[features] +experimental_parser = [] diff --git a/noir/noir-repo/compiler/noirc_frontend/build.rs b/noir/noir-repo/compiler/noirc_frontend/build.rs new file mode 100644 index 00000000000..eb896a377ae --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/build.rs @@ -0,0 +1,28 @@ +use std::fs::{read_to_string, File}; +use std::io::Write; + +fn main() { + lalrpop::Configuration::new() + .emit_rerun_directives(true) + .use_cargo_dir_conventions() + .process() + .unwrap(); + + // here, we get a lint error from "extern crate core" so patching that until lalrpop does + // (adding cfg directives appears to be unsupported by lalrpop) + let out_dir = std::env::var("OUT_DIR").unwrap(); + let parser_path = std::path::Path::new(&out_dir).join("noir_parser.rs"); + let content_str = read_to_string(parser_path.clone()).unwrap(); + let mut parser_file = File::create(parser_path).unwrap(); + for line in content_str.lines() { + if line.contains("extern crate core") { + parser_file + .write_all( + format!("{}\n", line.replace("extern crate core", "use core")).as_bytes(), + ) + .unwrap(); + } else { + parser_file.write_all(format!("{}\n", line).as_bytes()).unwrap(); + } + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs index 4547dc2a176..254ec4a7590 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/mod.rs @@ -112,6 +112,9 @@ pub enum UnresolvedTypeData { /*env:*/ Box, ), + // The type of quoted code for metaprogramming + Code, + Unspecified, // This is for when the user declares a variable without specifying it's type Error, } @@ -200,6 +203,7 @@ impl std::fmt::Display for UnresolvedTypeData { } } MutableReference(element) => write!(f, "&mut {element}"), + Code => write!(f, "Code"), Unit => write!(f, "()"), Error => write!(f, "error"), Unspecified => write!(f, "unspecified"), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_ast.rs new file mode 100644 index 00000000000..8ffcbce7d62 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/hir_to_ast.rs @@ -0,0 +1,350 @@ +use iter_extended::vecmap; +use noirc_errors::{Span, Spanned}; + +use crate::ast::{ConstrainStatement, Expression, Statement, StatementKind}; +use crate::hir_def::expr::{HirArrayLiteral, HirExpression, HirIdent}; +use crate::hir_def::stmt::{HirLValue, HirPattern, HirStatement}; +use crate::macros_api::HirLiteral; +use crate::node_interner::{ExprId, NodeInterner, StmtId}; +use crate::{ + ArrayLiteral, AssignStatement, BlockExpression, CallExpression, CastExpression, ConstrainKind, + ConstructorExpression, ExpressionKind, ForLoopStatement, ForRange, Ident, IfExpression, + IndexExpression, InfixExpression, LValue, Lambda, LetStatement, Literal, + MemberAccessExpression, MethodCallExpression, Path, Pattern, PrefixExpression, Type, + UnresolvedType, UnresolvedTypeData, UnresolvedTypeExpression, +}; + +// TODO: +// - Full path for idents & types +// - Assert/AssertEq information lost +// - The type name span is lost in constructor patterns & expressions +// - All type spans are lost +// - Type::TypeVariable has no equivalent in the Ast + +impl StmtId { + #[allow(unused)] + fn to_ast(self, interner: &NodeInterner) -> Statement { + let statement = interner.statement(&self); + let span = interner.statement_span(&self); + + let kind = match statement { + HirStatement::Let(let_stmt) => { + let pattern = let_stmt.pattern.into_ast(interner); + let r#type = interner.id_type(let_stmt.expression).to_ast(); + let expression = let_stmt.expression.to_ast(interner); + StatementKind::Let(LetStatement { + pattern, + r#type, + expression, + attributes: Vec::new(), + }) + } + HirStatement::Constrain(constrain) => { + let expr = constrain.0.to_ast(interner); + let message = constrain.2.map(|message| message.to_ast(interner)); + + // TODO: Find difference in usage between Assert & AssertEq + StatementKind::Constrain(ConstrainStatement(expr, message, ConstrainKind::Assert)) + } + HirStatement::Assign(assign) => StatementKind::Assign(AssignStatement { + lvalue: assign.lvalue.into_ast(interner), + expression: assign.expression.to_ast(interner), + }), + HirStatement::For(for_stmt) => StatementKind::For(ForLoopStatement { + identifier: for_stmt.identifier.to_ast(interner), + range: ForRange::Range( + for_stmt.start_range.to_ast(interner), + for_stmt.end_range.to_ast(interner), + ), + block: for_stmt.block.to_ast(interner), + span, + }), + HirStatement::Break => StatementKind::Break, + HirStatement::Continue => StatementKind::Continue, + HirStatement::Expression(expr) => StatementKind::Expression(expr.to_ast(interner)), + HirStatement::Semi(expr) => StatementKind::Semi(expr.to_ast(interner)), + HirStatement::Error => StatementKind::Error, + }; + + Statement { kind, span } + } +} + +impl ExprId { + #[allow(unused)] + fn to_ast(self, interner: &NodeInterner) -> Expression { + let expression = interner.expression(&self); + let span = interner.expr_span(&self); + + let kind = match expression { + HirExpression::Ident(ident) => { + let path = Path::from_ident(ident.to_ast(interner)); + ExpressionKind::Variable(path) + } + HirExpression::Literal(HirLiteral::Array(array)) => { + let array = array.into_ast(interner, span); + ExpressionKind::Literal(Literal::Array(array)) + } + HirExpression::Literal(HirLiteral::Slice(array)) => { + let array = array.into_ast(interner, span); + ExpressionKind::Literal(Literal::Slice(array)) + } + HirExpression::Literal(HirLiteral::Bool(value)) => { + ExpressionKind::Literal(Literal::Bool(value)) + } + HirExpression::Literal(HirLiteral::Integer(value, sign)) => { + ExpressionKind::Literal(Literal::Integer(value, sign)) + } + HirExpression::Literal(HirLiteral::Str(string)) => { + ExpressionKind::Literal(Literal::Str(string)) + } + HirExpression::Literal(HirLiteral::FmtStr(string, _exprs)) => { + // TODO: Is throwing away the exprs here valid? + ExpressionKind::Literal(Literal::FmtStr(string)) + } + HirExpression::Literal(HirLiteral::Unit) => ExpressionKind::Literal(Literal::Unit), + HirExpression::Block(expr) => { + let statements = vecmap(expr.statements, |statement| statement.to_ast(interner)); + ExpressionKind::Block(BlockExpression { statements }) + } + HirExpression::Prefix(prefix) => ExpressionKind::Prefix(Box::new(PrefixExpression { + operator: prefix.operator, + rhs: prefix.rhs.to_ast(interner), + })), + HirExpression::Infix(infix) => ExpressionKind::Infix(Box::new(InfixExpression { + lhs: infix.lhs.to_ast(interner), + operator: Spanned::from(infix.operator.location.span, infix.operator.kind), + rhs: infix.rhs.to_ast(interner), + })), + HirExpression::Index(index) => ExpressionKind::Index(Box::new(IndexExpression { + collection: index.collection.to_ast(interner), + index: index.index.to_ast(interner), + })), + HirExpression::Constructor(constructor) => { + let type_name = constructor.r#type.borrow().name.to_string(); + let type_name = Path::from_single(type_name, span); + let fields = + vecmap(constructor.fields, |(name, expr)| (name, expr.to_ast(interner))); + + ExpressionKind::Constructor(Box::new(ConstructorExpression { type_name, fields })) + } + HirExpression::MemberAccess(access) => { + ExpressionKind::MemberAccess(Box::new(MemberAccessExpression { + lhs: access.lhs.to_ast(interner), + rhs: access.rhs, + })) + } + HirExpression::Call(call) => { + let func = Box::new(call.func.to_ast(interner)); + let arguments = vecmap(call.arguments, |arg| arg.to_ast(interner)); + ExpressionKind::Call(Box::new(CallExpression { func, arguments })) + } + HirExpression::MethodCall(method_call) => { + ExpressionKind::MethodCall(Box::new(MethodCallExpression { + object: method_call.object.to_ast(interner), + method_name: method_call.method, + arguments: vecmap(method_call.arguments, |arg| arg.to_ast(interner)), + })) + } + HirExpression::Cast(cast) => { + let lhs = cast.lhs.to_ast(interner); + let r#type = cast.r#type.to_ast(); + ExpressionKind::Cast(Box::new(CastExpression { lhs, r#type })) + } + HirExpression::If(if_expr) => ExpressionKind::If(Box::new(IfExpression { + condition: if_expr.condition.to_ast(interner), + consequence: if_expr.consequence.to_ast(interner), + alternative: if_expr.alternative.map(|expr| expr.to_ast(interner)), + })), + HirExpression::Tuple(fields) => { + ExpressionKind::Tuple(vecmap(fields, |field| field.to_ast(interner))) + } + HirExpression::Lambda(lambda) => { + let parameters = vecmap(lambda.parameters, |(pattern, typ)| { + (pattern.into_ast(interner), typ.to_ast()) + }); + let return_type = lambda.return_type.to_ast(); + let body = lambda.body.to_ast(interner); + ExpressionKind::Lambda(Box::new(Lambda { parameters, return_type, body })) + } + HirExpression::Quote(block) => ExpressionKind::Quote(block), + HirExpression::Error => ExpressionKind::Error, + }; + + Expression::new(kind, span) + } +} + +impl HirPattern { + fn into_ast(self, interner: &NodeInterner) -> Pattern { + match self { + HirPattern::Identifier(ident) => Pattern::Identifier(ident.to_ast(interner)), + HirPattern::Mutable(pattern, location) => { + let pattern = Box::new(pattern.into_ast(interner)); + Pattern::Mutable(pattern, location.span, false) + } + HirPattern::Tuple(patterns, location) => { + let patterns = vecmap(patterns, |pattern| pattern.into_ast(interner)); + Pattern::Tuple(patterns, location.span) + } + HirPattern::Struct(typ, patterns, location) => { + let patterns = + vecmap(patterns, |(name, pattern)| (name, pattern.into_ast(interner))); + let name = match typ.follow_bindings() { + Type::Struct(struct_def, _) => { + let struct_def = struct_def.borrow(); + struct_def.name.0.contents.clone() + } + // This pass shouldn't error so if the type isn't a struct we just get a string + // representation of any other type and use that. We're relying on name + // resolution to fail later when this Ast is re-converted to Hir. + other => other.to_string(), + }; + // The name span is lost here + let path = Path::from_single(name, location.span); + Pattern::Struct(path, patterns, location.span) + } + } + } +} + +impl HirIdent { + fn to_ast(&self, interner: &NodeInterner) -> Ident { + let name = interner.definition_name(self.id).to_owned(); + Ident(Spanned::from(self.location.span, name)) + } +} + +impl Type { + fn to_ast(&self) -> UnresolvedType { + let typ = match self { + Type::FieldElement => UnresolvedTypeData::FieldElement, + Type::Array(length, element) => { + let length = length.to_type_expression(); + let element = Box::new(element.to_ast()); + UnresolvedTypeData::Array(length, element) + } + Type::Slice(element) => { + let element = Box::new(element.to_ast()); + UnresolvedTypeData::Slice(element) + } + Type::Integer(sign, bit_size) => UnresolvedTypeData::Integer(*sign, *bit_size), + Type::Bool => UnresolvedTypeData::Bool, + Type::String(length) => { + let length = length.to_type_expression(); + UnresolvedTypeData::String(Some(length)) + } + Type::FmtString(length, element) => { + let length = length.to_type_expression(); + let element = Box::new(element.to_ast()); + UnresolvedTypeData::FormatString(length, element) + } + Type::Unit => UnresolvedTypeData::Unit, + Type::Tuple(fields) => { + let fields = vecmap(fields, |field| field.to_ast()); + UnresolvedTypeData::Tuple(fields) + } + Type::Struct(def, generics) => { + let struct_def = def.borrow(); + let generics = vecmap(generics, |generic| generic.to_ast()); + let name = Path::from_ident(struct_def.name.clone()); + UnresolvedTypeData::Named(name, generics, false) + } + Type::Alias(type_def, generics) => { + // Keep the alias name instead of expanding this in case the + // alias' definition was changed + let type_def = type_def.borrow(); + let generics = vecmap(generics, |generic| generic.to_ast()); + let name = Path::from_ident(type_def.name.clone()); + UnresolvedTypeData::Named(name, generics, false) + } + Type::TypeVariable(_, _) => todo!("Convert Type::TypeVariable Hir -> Ast"), + Type::TraitAsType(_, name, generics) => { + let generics = vecmap(generics, |generic| generic.to_ast()); + let name = Path::from_single(name.as_ref().clone(), Span::default()); + UnresolvedTypeData::TraitAsType(name, generics) + } + Type::NamedGeneric(_, name) => { + let name = Path::from_single(name.as_ref().clone(), Span::default()); + UnresolvedTypeData::TraitAsType(name, Vec::new()) + } + Type::Function(args, ret, env) => { + let args = vecmap(args, |arg| arg.to_ast()); + let ret = Box::new(ret.to_ast()); + let env = Box::new(env.to_ast()); + UnresolvedTypeData::Function(args, ret, env) + } + Type::MutableReference(element) => { + let element = Box::new(element.to_ast()); + UnresolvedTypeData::MutableReference(element) + } + // Type::Forall is only for generic functions which don't store a type + // in their Ast so they don't need to call to_ast for their Forall type. + // Since there is no UnresolvedTypeData equivalent for Type::Forall, we use + // this to ignore this case since it shouldn't be needed anyway. + Type::Forall(_, typ) => return typ.to_ast(), + Type::Constant(_) => panic!("Type::Constant where a type was expected: {self:?}"), + Type::Code => UnresolvedTypeData::Code, + Type::Error => UnresolvedTypeData::Error, + }; + + UnresolvedType { typ, span: None } + } + + fn to_type_expression(&self) -> UnresolvedTypeExpression { + let span = Span::default(); + + match self.follow_bindings() { + Type::Constant(length) => UnresolvedTypeExpression::Constant(length, span), + Type::NamedGeneric(_, name) => { + let path = Path::from_single(name.as_ref().clone(), span); + UnresolvedTypeExpression::Variable(path) + } + // TODO: This should be turned into a proper error. + other => panic!("Cannot represent {other:?} as type expression"), + } + } +} + +impl HirLValue { + fn into_ast(self, interner: &NodeInterner) -> LValue { + match self { + HirLValue::Ident(ident, _) => LValue::Ident(ident.to_ast(interner)), + HirLValue::MemberAccess { object, field_name, field_index: _, typ: _, location } => { + let object = Box::new(object.into_ast(interner)); + LValue::MemberAccess { object, field_name, span: location.span } + } + HirLValue::Index { array, index, typ: _, location } => { + let array = Box::new(array.into_ast(interner)); + let index = index.to_ast(interner); + LValue::Index { array, index, span: location.span } + } + HirLValue::Dereference { lvalue, element_type: _, location } => { + let lvalue = Box::new(lvalue.into_ast(interner)); + LValue::Dereference(lvalue, location.span) + } + } + } +} + +impl HirArrayLiteral { + fn into_ast(self, interner: &NodeInterner, span: Span) -> ArrayLiteral { + match self { + HirArrayLiteral::Standard(elements) => { + ArrayLiteral::Standard(vecmap(elements, |element| element.to_ast(interner))) + } + HirArrayLiteral::Repeated { repeated_element, length } => { + let repeated_element = Box::new(repeated_element.to_ast(interner)); + let length = match length { + Type::Constant(length) => { + let literal = Literal::Integer((length as u128).into(), false); + let kind = ExpressionKind::Literal(literal); + Box::new(Expression::new(kind, span)) + } + other => panic!("Cannot convert non-constant type for repeated array literal from Hir -> Ast: {other:?}"), + }; + ArrayLiteral::Repeated { repeated_element, length } + } + } + } +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs new file mode 100644 index 00000000000..91621c857cf --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/mod.rs @@ -0,0 +1 @@ +mod hir_to_ast; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/mod.rs index 727a6596df1..55dc22d6c5d 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/mod.rs @@ -1,3 +1,4 @@ +pub mod comptime; pub mod def_collector; pub mod def_map; pub mod resolution; @@ -157,7 +158,8 @@ impl Context<'_, '_> { } } - /// Recursively walks down the crate dependency graph from crate_id until we reach requested crate + /// Tries to find the requested crate in the current one's dependencies, + /// otherwise walks down the crate dependency graph from crate_id until we reach it. /// This is needed in case a library (lib1) re-export a structure defined in another library (lib2) /// In that case, we will get [lib1,lib2] when looking for a struct defined in lib2, /// re-exported by lib1 and used by the main crate. @@ -167,16 +169,26 @@ impl Context<'_, '_> { crate_id: &CrateId, target_crate_id: &CrateId, ) -> Option> { - for dep in &self.crate_graph[crate_id].dependencies { - if &dep.crate_id == target_crate_id { - return Some(vec![dep.name.to_string()]); - } - if let Some(mut path) = self.find_dependencies(&dep.crate_id, target_crate_id) { - path.insert(0, dep.name.to_string()); - return Some(path); - } - } - None + self.crate_graph[crate_id] + .dependencies + .iter() + .find_map(|dep| { + if &dep.crate_id == target_crate_id { + Some(vec![dep.name.to_string()]) + } else { + None + } + }) + .or_else(|| { + self.crate_graph[crate_id].dependencies.iter().find_map(|dep| { + if let Some(mut path) = self.find_dependencies(&dep.crate_id, target_crate_id) { + path.insert(0, dep.name.to_string()); + Some(path) + } else { + None + } + }) + }) } pub fn function_meta(&self, func_id: &FuncId) -> &FuncMeta { @@ -241,7 +253,7 @@ impl Context<'_, '_> { .get_all_contracts(&self.def_interner) } - fn module(&self, module_id: def_map::ModuleId) -> &def_map::ModuleData { + pub fn module(&self, module_id: def_map::ModuleId) -> &def_map::ModuleData { module_id.module(&self.def_maps) } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 08b12069d76..9180201fe17 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -502,6 +502,7 @@ impl<'a> Resolver<'a> { let fields = self.resolve_type_inner(*fields, new_variables); Type::FmtString(Box::new(resolved_size), Box::new(fields)) } + Code => Type::Code, Unit => Type::Unit, Unspecified => Type::Error, Error => Type::Error, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs index 265b9e4b5a3..2d1ebf530e3 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/lexer.rs @@ -2,7 +2,9 @@ use crate::token::{Attribute, DocStyle}; use super::{ errors::LexerErrorKind, - token::{IntType, Keyword, SpannedToken, Token, Tokens}, + token::{ + token_to_borrowed_token, BorrowedToken, IntType, Keyword, SpannedToken, Token, Tokens, + }, }; use acvm::FieldElement; use noirc_errors::{Position, Span}; @@ -21,6 +23,21 @@ pub struct Lexer<'a> { pub type SpannedTokenResult = Result; +pub(crate) fn from_spanned_token_result( + token_result: &SpannedTokenResult, +) -> Result<(usize, BorrowedToken<'_>, usize), LexerErrorKind> { + token_result + .as_ref() + .map(|spanned_token| { + ( + spanned_token.to_span().start() as usize, + token_to_borrowed_token(spanned_token.into()), + spanned_token.to_span().end() as usize, + ) + }) + .map_err(Clone::clone) +} + impl<'a> Lexer<'a> { /// Given a source file of noir code, return all the tokens in the file /// in order, along with any lexing errors that occurred. @@ -94,7 +111,7 @@ impl<'a> Lexer<'a> { fn next_token(&mut self) -> SpannedTokenResult { match self.next_char() { - Some(x) if x.is_whitespace() => { + Some(x) if Self::is_code_whitespace(x) => { let spanned = self.eat_whitespace(x); if self.skip_whitespaces { self.next_token() @@ -560,16 +577,21 @@ impl<'a> Lexer<'a> { } } + fn is_code_whitespace(c: char) -> bool { + c == '\t' || c == '\n' || c == '\r' || c == ' ' + } + /// Skips white space. They are not significant in the source language fn eat_whitespace(&mut self, initial_char: char) -> SpannedToken { let start = self.position; - let whitespace = self.eat_while(initial_char.into(), |ch| ch.is_whitespace()); + let whitespace = self.eat_while(initial_char.into(), Self::is_code_whitespace); SpannedToken::new(Token::Whitespace(whitespace), Span::inclusive(start, self.position)) } } impl<'a> Iterator for Lexer<'a> { type Item = SpannedTokenResult; + fn next(&mut self) -> Option { if self.done { None @@ -578,10 +600,12 @@ impl<'a> Iterator for Lexer<'a> { } } } + #[cfg(test)] mod tests { use super::*; use crate::token::{FunctionAttribute, SecondaryAttribute, TestScope}; + #[test] fn test_single_double_char() { let input = "! != + ( ) { } [ ] | , ; : :: < <= > >= & - -> . .. % / * = == << >>"; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index 357b1ead593..86f26fd1c97 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -9,12 +9,105 @@ use crate::lexer::errors::LexerErrorKind; /// smallest unit of grammar. A parser may (will) decide to parse /// items differently depending on the Tokens present but will /// never parse the same ordering of identical tokens differently. +#[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] +pub enum BorrowedToken<'input> { + Ident(&'input str), + Int(FieldElement), + Bool(bool), + Str(&'input str), + /// the u8 is the number of hashes, i.e. r###.. + RawStr(&'input str, u8), + FmtStr(&'input str), + Keyword(Keyword), + IntType(IntType), + Attribute(Attribute), + LineComment(&'input str, Option), + BlockComment(&'input str, Option), + /// < + Less, + /// <= + LessEqual, + /// > + Greater, + /// >= + GreaterEqual, + /// == + Equal, + /// != + NotEqual, + /// + + Plus, + /// - + Minus, + /// * + Star, + /// / + Slash, + /// % + Percent, + /// & + Ampersand, + /// ^ + Caret, + /// << + ShiftLeft, + /// >> + ShiftRight, + /// . + Dot, + /// .. + DoubleDot, + /// ( + LeftParen, + /// ) + RightParen, + /// { + LeftBrace, + /// } + RightBrace, + /// [ + LeftBracket, + /// ] + RightBracket, + /// -> + Arrow, + /// | + Pipe, + /// # + Pound, + /// , + Comma, + /// : + Colon, + /// :: + DoubleColon, + /// ; + Semicolon, + /// ! + Bang, + /// = + Assign, + #[allow(clippy::upper_case_acronyms)] + EOF, + + Whitespace(&'input str), + + /// An invalid character is one that is not in noir's language or grammar. + /// + /// We don't report invalid tokens in the source as errors until parsing to + /// avoid reporting the error twice (once while lexing, again when it is encountered + /// during parsing). Reporting during lexing then removing these from the token stream + /// would not be equivalent as it would change the resulting parse. + Invalid(char), +} + #[derive(PartialEq, Eq, Hash, Debug, Clone, PartialOrd, Ord)] pub enum Token { Ident(String), Int(FieldElement), Bool(bool), Str(String), + /// the u8 is the number of hashes, i.e. r###.. RawStr(String, u8), FmtStr(String), Keyword(Keyword), @@ -100,6 +193,57 @@ pub enum Token { Invalid(char), } +pub fn token_to_borrowed_token(token: &Token) -> BorrowedToken<'_> { + match token { + Token::Ident(ref s) => BorrowedToken::Ident(s), + Token::Int(n) => BorrowedToken::Int(*n), + Token::Bool(b) => BorrowedToken::Bool(*b), + Token::Str(ref b) => BorrowedToken::Str(b), + Token::FmtStr(ref b) => BorrowedToken::FmtStr(b), + Token::RawStr(ref b, hashes) => BorrowedToken::RawStr(b, *hashes), + Token::Keyword(k) => BorrowedToken::Keyword(*k), + Token::Attribute(ref a) => BorrowedToken::Attribute(a.clone()), + Token::LineComment(ref s, _style) => BorrowedToken::LineComment(s, *_style), + Token::BlockComment(ref s, _style) => BorrowedToken::BlockComment(s, *_style), + Token::IntType(ref i) => BorrowedToken::IntType(i.clone()), + Token::Less => BorrowedToken::Less, + Token::LessEqual => BorrowedToken::LessEqual, + Token::Greater => BorrowedToken::Greater, + Token::GreaterEqual => BorrowedToken::GreaterEqual, + Token::Equal => BorrowedToken::Equal, + Token::NotEqual => BorrowedToken::NotEqual, + Token::Plus => BorrowedToken::Plus, + Token::Minus => BorrowedToken::Minus, + Token::Star => BorrowedToken::Star, + Token::Slash => BorrowedToken::Slash, + Token::Percent => BorrowedToken::Percent, + Token::Ampersand => BorrowedToken::Ampersand, + Token::Caret => BorrowedToken::Caret, + Token::ShiftLeft => BorrowedToken::ShiftLeft, + Token::ShiftRight => BorrowedToken::ShiftRight, + Token::Dot => BorrowedToken::Dot, + Token::DoubleDot => BorrowedToken::DoubleDot, + Token::LeftParen => BorrowedToken::LeftParen, + Token::RightParen => BorrowedToken::RightParen, + Token::LeftBrace => BorrowedToken::LeftBrace, + Token::RightBrace => BorrowedToken::RightBrace, + Token::LeftBracket => BorrowedToken::LeftBracket, + Token::RightBracket => BorrowedToken::RightBracket, + Token::Arrow => BorrowedToken::Arrow, + Token::Pipe => BorrowedToken::Pipe, + Token::Pound => BorrowedToken::Pound, + Token::Comma => BorrowedToken::Comma, + Token::Colon => BorrowedToken::Colon, + Token::DoubleColon => BorrowedToken::DoubleColon, + Token::Semicolon => BorrowedToken::Semicolon, + Token::Assign => BorrowedToken::Assign, + Token::Bang => BorrowedToken::Bang, + Token::EOF => BorrowedToken::EOF, + Token::Invalid(c) => BorrowedToken::Invalid(*c), + Token::Whitespace(ref s) => BorrowedToken::Whitespace(s), + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] pub enum DocStyle { Outer, @@ -126,6 +270,12 @@ impl From for Token { } } +impl<'a> From<&'a SpannedToken> for &'a Token { + fn from(spt: &'a SpannedToken) -> Self { + &spt.0.contents + } +} + impl SpannedToken { pub fn new(token: Token, span: Span) -> SpannedToken { SpannedToken(Spanned::from(span, token)) diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs index 7d20c2bcfee..d9c33d8604e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -92,6 +92,7 @@ pub enum Literal { Slice(ArrayLiteral), Integer(FieldElement, Type, Location), Bool(bool), + Unit, Str(String), FmtStr(String, u64, Box), } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index 6aa0abce152..4e779244d30 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -52,14 +52,13 @@ struct LambdaContext { /// This struct holds the FIFO queue of functions to monomorphize, which is added to /// whenever a new (function, type) combination is encountered. struct Monomorphizer<'interner> { - /// Globals are keyed by their unique ID and expected type so that we can monomorphize - /// a new version of the global for each type. Note that 'global' here means 'globally - /// visible' and thus includes both functions and global variables. + /// Functions are keyed by their unique ID and expected type so that we can monomorphize + /// a new version of the function for each type. /// /// Using nested HashMaps here lets us avoid cloning HirTypes when calling .get() - globals: HashMap>, + functions: HashMap>, - /// Unlike globals, locals are only keyed by their unique ID because they are never + /// Unlike functions, locals are only keyed by their unique ID because they are never /// duplicated during monomorphization. Doing so would allow them to be used polymorphically /// but would also cause them to be re-evaluated which is a performance trap that would /// confuse users. @@ -165,7 +164,7 @@ pub fn monomorphize_debug( impl<'interner> Monomorphizer<'interner> { fn new(interner: &'interner mut NodeInterner, debug_type_tracker: DebugTypeTracker) -> Self { Monomorphizer { - globals: HashMap::new(), + functions: HashMap::new(), locals: HashMap::new(), queue: VecDeque::new(), finished_functions: BTreeMap::new(), @@ -203,7 +202,7 @@ impl<'interner> Monomorphizer<'interner> { trait_method: Option, ) -> Definition { let typ = typ.follow_bindings(); - match self.globals.get(&id).and_then(|inner_map| inner_map.get(&typ)) { + match self.functions.get(&id).and_then(|inner_map| inner_map.get(&typ)) { Some(id) => Definition::Function(*id), None => { // Function has not been monomorphized yet @@ -251,8 +250,8 @@ impl<'interner> Monomorphizer<'interner> { } /// Prerequisite: typ = typ.follow_bindings() - fn define_global(&mut self, id: node_interner::FuncId, typ: HirType, new_id: FuncId) { - self.globals.entry(id).or_default().insert(typ, new_id); + fn define_function(&mut self, id: node_interner::FuncId, typ: HirType, new_id: FuncId) { + self.functions.entry(id).or_default().insert(typ, new_id); } fn compile_main( @@ -786,7 +785,7 @@ impl<'interner> Monomorphizer<'interner> { }) } - /// A local (ie non-global) ident only + /// A local (ie non-function) ident only fn local_ident( &mut self, ident: &HirIdent, @@ -1280,7 +1279,7 @@ impl<'interner> Monomorphizer<'interner> { trait_method: Option, ) -> FuncId { let new_id = self.next_function_id(); - self.define_global(id, function_type.clone(), new_id); + self.define_function(id, function_type.clone(), new_id); let bindings = self.interner.get_instantiation_bindings(expr_id); let bindings = self.follow_bindings(bindings); @@ -1553,9 +1552,7 @@ impl<'interner> Monomorphizer<'interner> { ast::Expression::Literal(ast::Literal::Integer(0_u128.into(), typ, location)) } ast::Type::Bool => ast::Expression::Literal(ast::Literal::Bool(false)), - // There is no unit literal currently. Replace it with 'false' since it should be ignored - // anyway. - ast::Type::Unit => ast::Expression::Literal(ast::Literal::Bool(false)), + ast::Type::Unit => ast::Expression::Literal(ast::Literal::Unit), ast::Type::Array(length, element_type) => { let element = self.zeroed_value_of_type(element_type.as_ref(), location); ast::Expression::Literal(ast::Literal::Array(ast::ArrayLiteral { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/printer.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/printer.rs index c253bfe7930..ea8f079cc2f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/printer.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/printer.rs @@ -110,6 +110,9 @@ impl AstPrinter { s.fmt(f)?; write!(f, "\"") } + super::ast::Literal::Unit => { + write!(f, "()") + } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs index ffd760d6d7f..153c7e45d4a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -223,10 +223,10 @@ pub enum TraitImplKind { /// /// Additionally, types can define specialized impls with methods of the same name /// as long as these specialized impls do not overlap. E.g. `impl Struct` and `impl Struct` -#[derive(Default, Debug)] +#[derive(Default, Debug, Clone)] pub struct Methods { - direct: Vec, - trait_impl_methods: Vec, + pub direct: Vec, + pub trait_impl_methods: Vec, } /// All the information from a function that is filled out during definition collection rather than @@ -917,10 +917,32 @@ impl NodeInterner { self.id_location(expr_id) } + pub fn statement_span(&self, stmt_id: &StmtId) -> Span { + self.id_location(stmt_id).span + } + pub fn get_struct(&self, id: StructId) -> Shared { self.structs[&id].clone() } + pub fn get_struct_methods(&self, id: StructId) -> Vec { + self.struct_methods + .keys() + .filter_map(|(key_id, name)| { + if key_id == &id { + Some( + self.struct_methods + .get(&(*key_id, name.clone())) + .expect("get_struct_methods given invalid StructId") + .clone(), + ) + } else { + None + } + }) + .collect() + } + pub fn get_trait(&self, id: TraitId) -> &Trait { &self.traits[&id] } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop b/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop new file mode 100644 index 00000000000..c8d293fb72f --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/noir_parser.lalrpop @@ -0,0 +1,164 @@ +use noirc_errors::Span; + +use crate::lexer::token::BorrowedToken; +use crate::lexer::token as noir_token; +use crate::lexer::errors::LexerErrorKind; +use crate::parser::TopLevelStatement; +use crate::{Ident, Path, PathKind, UseTree, UseTreeKind}; + +use lalrpop_util::ErrorRecovery; + +grammar<'input, 'err>(input: &'input str, errors: &'err mut [ErrorRecovery, &'static str>]); + +extern { + type Location = usize; + + type Error = LexerErrorKind; + + // NOTE: each token needs a terminal defined + enum BorrowedToken<'input> { + string => BorrowedToken::Str(<&'input str>), + ident => BorrowedToken::Ident(<&'input str>), + + // symbols + "<" => BorrowedToken::Less, + "<=" => BorrowedToken::LessEqual, + ">" => BorrowedToken::Greater, + ">=" => BorrowedToken::GreaterEqual, + "==" => BorrowedToken::Equal, + "!=" => BorrowedToken::NotEqual, + "+" => BorrowedToken::Plus, + "-" => BorrowedToken::Minus, + "*" => BorrowedToken::Star, + "/" => BorrowedToken::Slash, + "%" => BorrowedToken::Percent, + "&" => BorrowedToken::Ampersand, + "^" => BorrowedToken::Caret, + "<<" => BorrowedToken::ShiftLeft, + ">>" => BorrowedToken::ShiftRight, + "." => BorrowedToken::Dot, + ".." => BorrowedToken::DoubleDot, + "(" => BorrowedToken::LeftParen, + ")" => BorrowedToken::RightParen, + "{" => BorrowedToken::LeftBrace, + "}" => BorrowedToken::RightBrace, + "[" => BorrowedToken::LeftBracket, + "]" => BorrowedToken::RightBracket, + "->" => BorrowedToken::Arrow, + "|" => BorrowedToken::Pipe, + "#" => BorrowedToken::Pound, + "," => BorrowedToken::Comma, + ":" => BorrowedToken::Colon, + "::" => BorrowedToken::DoubleColon, + ";" => BorrowedToken::Semicolon, + "!" => BorrowedToken::Bang, + "=" => BorrowedToken::Assign, + // keywords + "as" => BorrowedToken::Keyword(noir_token::Keyword::As), + "assert" => BorrowedToken::Keyword(noir_token::Keyword::Assert), + "assert_eq" => BorrowedToken::Keyword(noir_token::Keyword::AssertEq), + "bool" => BorrowedToken::Keyword(noir_token::Keyword::Bool), + "break" => BorrowedToken::Keyword(noir_token::Keyword::Break), + "call_data" => BorrowedToken::Keyword(noir_token::Keyword::CallData), + "char" => BorrowedToken::Keyword(noir_token::Keyword::Char), + "comptime" => BorrowedToken::Keyword(noir_token::Keyword::CompTime), + "constrain" => BorrowedToken::Keyword(noir_token::Keyword::Constrain), + "continue" => BorrowedToken::Keyword(noir_token::Keyword::Continue), + "contract" => BorrowedToken::Keyword(noir_token::Keyword::Contract), + "crate" => BorrowedToken::Keyword(noir_token::Keyword::Crate), + "dep" => BorrowedToken::Keyword(noir_token::Keyword::Dep), + "distinct" => BorrowedToken::Keyword(noir_token::Keyword::Distinct), + "else" => BorrowedToken::Keyword(noir_token::Keyword::Else), + "Field" => BorrowedToken::Keyword(noir_token::Keyword::Field), + "fn" => BorrowedToken::Keyword(noir_token::Keyword::Fn), + "for" => BorrowedToken::Keyword(noir_token::Keyword::For), + "fmtstr" => BorrowedToken::Keyword(noir_token::Keyword::FormatString), + "global" => BorrowedToken::Keyword(noir_token::Keyword::Global), + "if" => BorrowedToken::Keyword(noir_token::Keyword::If), + "impl" => BorrowedToken::Keyword(noir_token::Keyword::Impl), + "in" => BorrowedToken::Keyword(noir_token::Keyword::In), + "let" => BorrowedToken::Keyword(noir_token::Keyword::Let), + "mod" => BorrowedToken::Keyword(noir_token::Keyword::Mod), + "mut" => BorrowedToken::Keyword(noir_token::Keyword::Mut), + "pub" => BorrowedToken::Keyword(noir_token::Keyword::Pub), + "quote" => BorrowedToken::Keyword(noir_token::Keyword::Quote), + "return" => BorrowedToken::Keyword(noir_token::Keyword::Return), + "return_data" => BorrowedToken::Keyword(noir_token::Keyword::ReturnData), + "str" => BorrowedToken::Keyword(noir_token::Keyword::String), + "struct" => BorrowedToken::Keyword(noir_token::Keyword::Struct), + "trait" => BorrowedToken::Keyword(noir_token::Keyword::Trait), + "type" => BorrowedToken::Keyword(noir_token::Keyword::Type), + "unchecked" => BorrowedToken::Keyword(noir_token::Keyword::Unchecked), + "unconstrained" => BorrowedToken::Keyword(noir_token::Keyword::Unconstrained), + "use" => BorrowedToken::Keyword(noir_token::Keyword::Use), + "where" => BorrowedToken::Keyword(noir_token::Keyword::Where), + "while" => BorrowedToken::Keyword(noir_token::Keyword::While), + // bool + "true" => BorrowedToken::Bool(true), + "false" => BorrowedToken::Bool(false), + + r"[\t\r\n ]+" => BorrowedToken::Whitespace(_), + + EOF => BorrowedToken::EOF, + } +} + +pub(crate) TopLevelStatement: TopLevelStatement = { + "use" r"[\t\r\n ]+" ";" EOF => { + TopLevelStatement::Import(use_tree) + } +} + +UseTree: UseTree = { + // path::to::ident as SomeAlias + => { + let ident = prefix.pop(); + let kind = UseTreeKind::Path(ident, alias); + UseTree { prefix, kind } + }, +} + +pub(crate) Path: Path = { + "crate" "::" => { + let kind = PathKind::Crate; + let span = Span::from(lo as u32..hi as u32); + Path { segments, kind, span } + }, + + "dep" "::" => { + let kind = PathKind::Dep; + let span = Span::from(lo as u32..hi as u32); + Path { segments, kind, span } + }, + + => { + segments.insert(0, id); + let kind = PathKind::Plain; + let span = Span::from(lo as u32..hi as u32); + Path { segments, kind, span } + }, +} + +PathSegments: Vec = { + )*> => { + segments + } +} + +Alias: Ident = { + r"[\t\r\n ]+" "as" r"[\t\r\n ]+" => <>, +} + +Ident: Ident = { + => { + let token = noir_token::Token::Ident(i.to_string()); + let span = Span::from(lo as u32..hi as u32); + Ident::from_token(token, span) + }, +} + +Bool: BorrowedToken<'input> = { + "true" => BorrowedToken::Bool(true), + "false" => BorrowedToken::Bool(false), +}; + 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 43a1f96f13f..895d4e07bbd 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/errors.rs @@ -110,25 +110,31 @@ impl ParserError { impl std::fmt::Display for ParserError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let reason_str: String = if self.reason.is_none() { + "".to_string() + } else { + format!("\nreason: {}", Diagnostic::from(self.clone())) + }; let mut expected = vecmap(&self.expected_tokens, ToString::to_string); expected.append(&mut vecmap(&self.expected_labels, |label| format!("{label}"))); if expected.is_empty() { - write!(f, "Unexpected {} in input", self.found) + write!(f, "Unexpected {} in input{}", self.found, reason_str) } else if expected.len() == 1 { let first = expected.first().unwrap(); let vowel = "aeiou".contains(first.chars().next().unwrap()); write!( f, - "Expected a{} {} but found {}", + "Expected a{} {} but found {}{}", if vowel { "n" } else { "" }, first, - self.found + self.found, + reason_str ) } else { let expected = expected.iter().map(ToString::to_string).collect::>().join(", "); - write!(f, "Unexpected {}, expected one of {}", self.found, expected) + write!(f, "Unexpected {}, expected one of {}{}", self.found, expected, reason_str) } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs index ea96dee8a47..80c5f47f07b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/mod.rs @@ -97,14 +97,14 @@ where /// Sequence the two parsers. /// Fails if the first parser fails, otherwise forces /// the second parser to succeed while logging any errors. -fn then_commit<'a, P1, P2, T1, T2: 'a>( +fn then_commit<'a, P1, P2, T1, T2>( first_parser: P1, second_parser: P2, ) -> impl NoirParser<(T1, T2)> + 'a where P1: NoirParser + 'a, P2: NoirParser + 'a, - T2: Clone + Recoverable, + T2: Clone + Recoverable + 'a, { let second_parser = skip_then_retry_until(second_parser) .map_with_span(|option, span| option.unwrap_or_else(|| Recoverable::error(span))); @@ -112,14 +112,15 @@ where first_parser.then(second_parser) } -fn then_commit_ignore<'a, P1, P2, T1: 'a, T2: 'a>( +fn then_commit_ignore<'a, P1, P2, T1, T2>( first_parser: P1, second_parser: P2, ) -> impl NoirParser + 'a where P1: NoirParser + 'a, P2: NoirParser + 'a, - T2: Clone, + T1: 'a, + T2: Clone + 'a, { let second_parser = skip_then_retry_until(second_parser); first_parser.then_ignore(second_parser) @@ -140,10 +141,10 @@ where first_parser.ignore_then(second_parser) } -fn skip_then_retry_until<'a, P, T: 'a>(parser: P) -> impl NoirParser> + 'a +fn skip_then_retry_until<'a, P, T>(parser: P) -> impl NoirParser> + 'a where P: NoirParser + 'a, - T: Clone, + T: Clone + 'a, { let terminators = [ Token::EOF, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs index 0a21465fe87..5706c3ef12f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/parser/parser.rs @@ -35,7 +35,7 @@ use super::{spanned, Item, ItemKind}; use crate::ast::{ Expression, ExpressionKind, LetStatement, StatementKind, UnresolvedType, UnresolvedTypeData, }; -use crate::lexer::Lexer; +use crate::lexer::{lexer::from_spanned_token_result, Lexer}; use crate::parser::{force, ignore_then_commit, statement_recovery}; use crate::token::{Keyword, Token, TokenKind}; use crate::{ @@ -47,6 +47,7 @@ use crate::{ use chumsky::prelude::*; use iter_extended::vecmap; +use lalrpop_util::lalrpop_mod; use noirc_errors::{Span, Spanned}; mod assertion; @@ -59,6 +60,9 @@ mod primitives; mod structs; mod traits; +// synthesized by LALRPOP +lalrpop_mod!(pub noir_parser); + #[cfg(test)] mod test_helpers; @@ -77,8 +81,79 @@ pub fn parse_program(source_program: &str) -> (ParsedModule, Vec) { let (module, mut parsing_errors) = program().parse_recovery_verbose(tokens); parsing_errors.extend(lexing_errors.into_iter().map(Into::into)); + let parsed_module = module.unwrap_or(ParsedModule { items: vec![] }); + + if cfg!(feature = "experimental_parser") { + for parsed_item in &parsed_module.items { + if lalrpop_parser_supports_kind(&parsed_item.kind) { + match &parsed_item.kind { + ItemKind::Import(parsed_use_tree) => { + prototype_parse_use_tree(Some(parsed_use_tree), source_program); + } + // other kinds prevented by lalrpop_parser_supports_kind + _ => unreachable!(), + } + } + } + } + (parsed_module, parsing_errors) +} + +fn prototype_parse_use_tree(expected_use_tree_opt: Option<&UseTree>, input: &str) { + // TODO(https://github.com/noir-lang/noir/issues/4777): currently skipping + // recursive use trees, e.g. "use std::{foo, bar}" + if input.contains('{') { + return; + } + + let mut lexer = Lexer::new(input); + lexer = lexer.skip_whitespaces(false); + let mut errors = Vec::new(); + + // NOTE: this is a hack to get the references working + // => this likely means that we'll want to propagate the <'input> lifetime further into Token + let lexer_result = lexer.collect::>(); + let referenced_lexer_result = lexer_result.iter().map(from_spanned_token_result); + + let calculated = noir_parser::TopLevelStatementParser::new().parse( + input, + &mut errors, + referenced_lexer_result, + ); + + if let Some(expected_use_tree) = expected_use_tree_opt { + assert!( + calculated.is_ok(), + "calculated not Ok(_): {:?}\n\nlexer: {:?}\n\ninput: {:?}", + calculated, + lexer_result, + input + ); + + match calculated.unwrap() { + TopLevelStatement::Import(parsed_use_tree) => { + assert_eq!(expected_use_tree, &parsed_use_tree); + } + unexpected_calculated => { + panic!( + "expected a TopLevelStatement::Import, but found: {:?}", + unexpected_calculated + ) + } + } + } else { + assert!( + calculated.is_err(), + "calculated not Err(_): {:?}\n\nlexer: {:?}\n\ninput: {:?}", + calculated, + lexer_result, + input + ); + } +} - (module.unwrap_or(ParsedModule { items: vec![] }), parsing_errors) +fn lalrpop_parser_supports_kind(kind: &ItemKind) -> bool { + matches!(kind, ItemKind::Import(_)) } /// program: module EOF @@ -1512,33 +1587,53 @@ mod test { #[test] fn parse_use() { - parse_all( - use_statement(), - vec![ - "use std::hash", - "use std", - "use foo::bar as hello", - "use bar as bar", - "use foo::{}", - "use foo::{bar,}", - "use foo::{bar, hello}", - "use foo::{bar as bar2, hello}", - "use foo::{bar as bar2, hello::{foo}, nested::{foo, bar}}", - "use dep::{std::println, bar::baz}", - ], - ); + let valid_use_statements = [ + "use std::hash", + "use std", + "use foo::bar as hello", + "use bar as bar", + "use foo::{}", + "use foo::{bar,}", + "use foo::{bar, hello}", + "use foo::{bar as bar2, hello}", + "use foo::{bar as bar2, hello::{foo}, nested::{foo, bar}}", + "use dep::{std::println, bar::baz}", + ]; - parse_all_failing( - use_statement(), - vec![ - "use std as ;", - "use foobar as as;", - "use hello:: as foo;", - "use foo bar::baz", - "use foo bar::{baz}", - "use foo::{,}", - ], - ); + let invalid_use_statements = [ + "use std as ;", + "use foobar as as;", + "use hello:: as foo;", + "use foo bar::baz", + "use foo bar::{baz}", + "use foo::{,}", + ]; + + let use_statements = valid_use_statements + .into_iter() + .map(|valid_str| (valid_str, true)) + .chain(invalid_use_statements.into_iter().map(|invalid_str| (invalid_str, false))); + + for (use_statement_str, expect_valid) in use_statements { + let mut use_statement_str = use_statement_str.to_string(); + let expected_use_statement = if expect_valid { + let (result_opt, _diagnostics) = + parse_recover(&use_statement(), &use_statement_str); + use_statement_str.push(';'); + match result_opt.unwrap() { + TopLevelStatement::Import(expected_use_statement) => { + Some(expected_use_statement) + } + _ => unreachable!(), + } + } else { + let result = parse_with(&use_statement(), &use_statement_str); + assert!(result.is_err()); + None + }; + + prototype_parse_use_tree(expected_use_statement.as_ref(), &use_statement_str); + } } #[test] diff --git a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs index c4f0a8d67ba..e4d308fbb6b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/tests.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/tests.rs @@ -66,7 +66,7 @@ mod test { // Allocate a default Module for the root, giving it a ModuleId let mut modules: Arena = Arena::default(); let location = Location::new(Default::default(), root_file_id); - let root = modules.insert(ModuleData::new(None, location, false)); + let root = modules.insert(ModuleData::new(None, None, location, false)); let def_map = CrateDefMap { root: LocalModuleId(root), diff --git a/noir/noir-repo/compiler/wasm/src/types/noir_artifact.ts b/noir/noir-repo/compiler/wasm/src/types/noir_artifact.ts index f241b539dc7..6ecc3ccd56f 100644 --- a/noir/noir-repo/compiler/wasm/src/types/noir_artifact.ts +++ b/noir/noir-repo/compiler/wasm/src/types/noir_artifact.ts @@ -151,6 +151,16 @@ export interface DebugInfo { locations: Record; } +/** + * The debug information for a given program. + */ +export interface ProgramDebugInfo { + /** + * An array that maps to each function of a program. + */ + debug_infos: Array; +} + /** * Maps a file ID to its metadata for debugging purposes. */ diff --git a/noir/noir-repo/compiler/wasm/test/compiler/shared/compile.test.ts b/noir/noir-repo/compiler/wasm/test/compiler/shared/compile.test.ts index 52cef14968b..f9e37530cbc 100644 --- a/noir/noir-repo/compiler/wasm/test/compiler/shared/compile.test.ts +++ b/noir/noir-repo/compiler/wasm/test/compiler/shared/compile.test.ts @@ -5,6 +5,7 @@ import { ContractCompilationArtifacts, DebugFileMap, DebugInfo, + ProgramDebugInfo, NoirFunctionEntry, ProgramArtifact, ProgramCompilationArtifacts, @@ -15,7 +16,7 @@ export function shouldCompileProgramIdentically( expect: typeof Expect, timeout = 5000, ) { - it('both nargo and noir_wasm should compile identically', async () => { + it('both nargo and noir_wasm should compile program identically', async () => { // Compile! const { nargoArtifact, noirWasmArtifact } = await compileFn(); @@ -51,7 +52,7 @@ export function shouldCompileContractIdentically( expect: typeof Expect, timeout = 5000, ) { - it('both nargo and noir_wasm should compile identically', async () => { + it('both nargo and noir_wasm should compile contract identically', async () => { // Compile! const { nargoArtifact, noirWasmArtifact } = await compileFn(); @@ -90,7 +91,7 @@ function extractDebugInfos(fns: NoirFunctionEntry[]) { return fns.map((fn) => { const debugSymbols = inflateDebugSymbols(fn.debug_symbols); delete (fn as Partial).debug_symbols; - clearFileIdentifiers(debugSymbols); + clearFileIdentifiersProgram(debugSymbols); return debugSymbols; }); } @@ -113,6 +114,12 @@ function deleteContractDebugMetadata(contract: ContractArtifact) { return [extractDebugInfos(contract.functions), fileMap]; } +function clearFileIdentifiersProgram(debugSymbols: ProgramDebugInfo) { + debugSymbols.debug_infos.map((debug_info) => { + clearFileIdentifiers(debug_info); + }); +} + /** Clears file identifiers from a set of debug symbols. */ function clearFileIdentifiers(debugSymbols: DebugInfo) { for (const loc of Object.values(debugSymbols.locations)) { diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 16de9757fb8..bf3040265c2 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -113,6 +113,7 @@ "Maddiaa", "mathbb", "memfs", + "memset", "merkle", "metas", "minreq", diff --git a/noir/noir-repo/deny.toml b/noir/noir-repo/deny.toml index eff233687e8..db7e53cad24 100644 --- a/noir/noir-repo/deny.toml +++ b/noir/noir-repo/deny.toml @@ -58,7 +58,7 @@ allow = [ # bitmaps 2.1.0, im 15.1.0 "MPL-2.0", # Boost Software License - "BSL-1.0", + "BSL-1.0" ] # Allow 1 or more licenses on a per-crate basis, so that particular licenses @@ -70,6 +70,7 @@ exceptions = [ { 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" }, diff --git a/noir/noir-repo/docs/docs/getting_started/tooling/index.mdx b/noir/noir-repo/docs/docs/getting_started/tooling/index.mdx deleted file mode 100644 index ac480f3c9f5..00000000000 --- a/noir/noir-repo/docs/docs/getting_started/tooling/index.mdx +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Tooling -Description: This section provides information about the various tools and utilities available for Noir development. It covers the Noir playground, IDE tools, Codespaces, and community projects. -Keywords: [Noir, Development, Playground, IDE Tools, Language Service Provider, VS Code Extension, Codespaces, noir-starter, Community Projects, Awesome Noir Repository, Developer Tooling] ---- - -Noir is meant to be easy to develop with. For that reason, a number of utilities have been put together to ease the development process as much as feasible in the zero-knowledge world. - -## Playground - -The Noir playground is an easy way to test small ideas, share snippets, and integrate in other websites. You can access it at [play.noir-lang.org](https://play.noir-lang.org). - -## IDE tools - -When you install Nargo, you're also installing a Language Service Provider (LSP), which can be used by IDEs to provide syntax highlighting, codelens, warnings, and more. - -The easiest way to use these tools is by installing the [Noir VS Code extension](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). - -## Codespaces - -Some Noir repos have leveraged Codespaces in order to ease the development process. You can visit the [noir-starter](https://github.com/noir-lang/noir-starter) for an example. - - - -## GitHub Actions - -You can use `noirup` with GitHub Actions for CI/CD and automated testing. It is as simple as -installing `noirup` and running tests in your GitHub Action `yml` file. - -See the -[config file in the Noir repo](https://github.com/TomAFrench/noir-hashes/blob/master/.github/workflows/noir.yml) for an example usage. - -## Community projects - -As an open-source project, Noir has received many contributions over time. Some of them are related with developer tooling, and you can see some of them in [Awesome Noir repository](https://github.com/noir-lang/awesome-noir#dev-tools) diff --git a/noir/noir-repo/docs/docs/how_to/debugger/_category_.json b/noir/noir-repo/docs/docs/how_to/debugger/_category_.json new file mode 100644 index 00000000000..cc2cbb1c253 --- /dev/null +++ b/noir/noir-repo/docs/docs/how_to/debugger/_category_.json @@ -0,0 +1,6 @@ +{ + "label": "Debugging", + "position": 5, + "collapsible": true, + "collapsed": true +} diff --git a/noir/noir-repo/docs/docs/how_to/debugger/debugging_with_the_repl.md b/noir/noir-repo/docs/docs/how_to/debugger/debugging_with_the_repl.md new file mode 100644 index 00000000000..09e5bae68ad --- /dev/null +++ b/noir/noir-repo/docs/docs/how_to/debugger/debugging_with_the_repl.md @@ -0,0 +1,164 @@ +--- +title: Using the REPL Debugger +description: + Step by step guide on how to debug your Noir circuits with the REPL Debugger. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +#### Pre-requisites + +In order to use the REPL debugger, first you need to install recent enough versions of Nargo and vscode-noir. + +## Debugging a simple circuit + +Let's debug a simple circuit: + +```rust +fn main(x : Field, y : pub Field) { + assert(x != y); +} +``` + +To start the REPL debugger, using a terminal, go to a Noir circuit's home directory. Then: + +`$ nargo debug` + +You should be seeing this in your terminal: + +``` +[main] Starting debugger +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:9 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> +``` + +The debugger displays the current Noir code location, and it is now waiting for us to drive it. + +Let's first take a look at the available commands. For that we'll use the `help` command. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +Some commands operate only for unconstrained functions, such as `memory` and `memset`. If you try to use them while execution is paused at an ACIR opcode, the debugger will simply inform you that you are not executing unconstrained code: + +``` +> memory +Unconstrained VM memory not available +> +``` + +Before continuing, we can take a look at the initial witness map: + +``` +> witness +_0 = 1 +_1 = 2 +> +``` + +Cool, since `x==1`, `y==2`, and we want to check that `x != y`, our circuit should succeed. At this point we could intervene and use the witness setter command to change one of the witnesses. Let's set `y=3`, then back to 2, so we don't affect the expected result: + +``` +> witness +_0 = 1 +_1 = 2 +> witness 1 3 +_1 = 3 +> witness +_0 = 1 +_1 = 3 +> witness 1 2 +_1 = 2 +> witness +_0 = 1 +_1 = 2 +> +``` + +Now we can inspect the current state of local variables. For that we use the `vars` command. + +``` +> vars +> +``` + +We currently have no vars in context, since we are at the entry point of the program. Let's use `next` to execute until the next point in the program. + +``` +> vars +> next +At ~/noir-examples/recursion/circuits/main/src/main.nr:1:20 + 1 -> fn main(x : Field, y : pub Field) { + 2 assert(x != y); + 3 } +> vars +x:Field = 0x01 +``` + +As a result of stepping, the variable `x`, whose initial value comes from the witness map, is now in context and returned by `vars`. + +``` +> next + 1 fn main(x : Field, y : pub Field) { + 2 -> assert(x != y); + 3 } +> vars +y:Field = 0x02 +x:Field = 0x01 +``` + +Stepping again we can finally see both variables and their values. And now we can see that the next assertion should succeed. + +Let's continue to the end: + +``` +> continue +(Continuing execution...) +Finished execution +> q +[main] Circuit witness successfully solved +``` + +Upon quitting the debugger after a solved circuit, the resulting circuit witness gets saved, equivalent to what would happen if we had run the same circuit with `nargo execute`. + +We just went through the basics of debugging using Noir REPL debugger. For a comprehensive reference, check out [the reference page](../../reference/debugger/debugger_repl.md). diff --git a/noir/noir-repo/docs/docs/how_to/debugger/debugging_with_vs_code.md b/noir/noir-repo/docs/docs/how_to/debugger/debugging_with_vs_code.md new file mode 100644 index 00000000000..a5858c1a5eb --- /dev/null +++ b/noir/noir-repo/docs/docs/how_to/debugger/debugging_with_vs_code.md @@ -0,0 +1,68 @@ +--- +title: Using the VS Code Debugger +description: + Step by step guide on how to debug your Noir circuits with the VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +This guide will show you how to use VS Code with the vscode-noir extension to debug a Noir project. + +#### Pre-requisites + +- Nargo +- vscode-noir +- A Noir project with a `Nargo.toml`, `Prover.toml` and at least one Noir (`.nr`) containing an entry point function (typically `main`). + +## Running the debugger + +The easiest way to start debugging is to open the file you want to debug, and press `F5`. This will cause the debugger to launch, using your `Prover.toml` file as input. + +You should see something like this: + +![Debugger launched](@site/static/img/debugger/1-started.png) + +Let's inspect the state of the program. For that, we open VS Code's _Debug pane_. Look for this icon: + +![Debug pane icon](@site/static/img/debugger/2-icon.png) + +You will now see two categories of variables: Locals and Witness Map. + +![Debug pane expanded](@site/static/img/debugger/3-debug-pane.png) + +1. **Locals**: variables of your program. At this point in execution this section is empty, but as we step through the code it will get populated by `x`, `result`, `digest`, etc. + +2. **Witness map**: these are initially populated from your project's `Prover.toml` file. In this example, they will be used to populate `x` and `result` at the beginning of the `main` function. + +Most of the time you will probably be focusing mostly on locals, as they represent the high level state of your program. + +You might be interested in inspecting the witness map in case you are trying to solve a really low level issue in the compiler or runtime itself, so this concerns mostly advanced or niche users. + +Let's step through the program, by using the debugger buttons or their corresponding keyboard shortcuts. + +![Debugger buttons](@site/static/img/debugger/4-debugger-buttons.png) + +Now we can see in the variables pane that there's values for `digest`, `result` and `x`. + +![Inspecting locals](@site/static/img/debugger/5-assert.png) + +We can also inspect the values of variables by directly hovering on them on the code. + +![Hover locals](@site/static/img/debugger/6-hover.png) + +Let's set a break point at the `keccak256` function, so we can continue execution up to the point when it's first invoked without having to go one step at a time. + +We just need to click the to the right of the line number 18. Once the breakpoint appears, we can click the `continue` button or use its corresponding keyboard shortcut (`F5` by default). + +![Breakpoint](@site/static/img/debugger/7-break.png) + +Now we are debugging the `keccak256` function, notice the _Call Stack pane_ at the lower right. This lets us inspect the current call stack of our process. + +That covers most of the current debugger functionalities. Check out [the reference](../../reference/debugger/debugger_vscode.md) for more details on how to configure the debugger. \ No newline at end of file diff --git a/noir/noir-repo/docs/docs/how_to/merkle-proof.mdx b/noir/noir-repo/docs/docs/how_to/merkle-proof.mdx index 003c7019a93..16c425bed76 100644 --- a/noir/noir-repo/docs/docs/how_to/merkle-proof.mdx +++ b/noir/noir-repo/docs/docs/how_to/merkle-proof.mdx @@ -5,6 +5,7 @@ description: merkle tree with a specified root, at a given index. keywords: [merkle proof, merkle membership proof, Noir, rust, hash function, Pedersen, sha256, merkle tree] +sidebar_position: 4 --- Let's walk through an example of a merkle membership proof in Noir that proves that a given leaf is diff --git a/noir/noir-repo/docs/docs/noir/concepts/functions.md b/noir/noir-repo/docs/docs/noir/concepts/functions.md index 2c9bc33fdfc..f656cdfd97a 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/functions.md +++ b/noir/noir-repo/docs/docs/noir/concepts/functions.md @@ -62,7 +62,7 @@ fn main(x : [Field]) // can't compile, has variable size fn main(....// i think you got it by now ``` -Keep in mind [tests](../../getting_started/tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: +Keep in mind [tests](../../tooling/testing.md) don't differentiate between `main` and any other function. The following snippet passes tests, but won't compile or prove: ```rust fn main(x : [Field]) { @@ -190,7 +190,7 @@ Supported attributes include: - **deprecated**: mark the function as _deprecated_. Calling the function will generate a warning: `warning: use of deprecated function` - **field**: Used to enable conditional compilation of code depending on the field size. See below for more details - **oracle**: mark the function as _oracle_; meaning it is an external unconstrained function, implemented in noir_js. See [Unconstrained](./unconstrained.md) and [NoirJS](../../reference/NoirJS/noir_js/index.md) for more details. -- **test**: mark the function as unit tests. See [Tests](../../getting_started/tooling/testing.md) for more details +- **test**: mark the function as unit tests. See [Tests](../../tooling/testing.md) for more details ### Field Attribute diff --git a/noir/noir-repo/docs/docs/noir/concepts/oracles.md b/noir/noir-repo/docs/docs/noir/concepts/oracles.md index 2e6a6818d48..aa380b5f7b8 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/oracles.md +++ b/noir/noir-repo/docs/docs/noir/concepts/oracles.md @@ -11,6 +11,12 @@ keywords: sidebar_position: 6 --- +:::note + +This is an experimental feature that is not fully documented. If you notice any outdated information or potential improvements to this page, pull request contributions are very welcome: https://github.com/noir-lang/noir + +::: + Noir has support for Oracles via RPC calls. This means Noir will make an RPC call and use the return value for proof generation. Since Oracles are not resolved by Noir, they are [`unconstrained` functions](./unconstrained.md) @@ -21,3 +27,5 @@ You can declare an Oracle through the `#[oracle()]` flag. Example: #[oracle(get_number_sequence)] unconstrained fn get_number_sequence(_size: Field) -> [Field] {} ``` + +The timeout for when using an external RPC oracle resolver can be set with the `NARGO_FOREIGN_CALL_TIMEOUT` environment variable. This timeout is in units of milliseconds. diff --git a/noir/noir-repo/docs/docs/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/docs/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/noir/noir-repo/docs/docs/noir/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/docs/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/docs/noir/standard_library/bigint.md b/noir/noir-repo/docs/docs/noir/standard_library/bigint.md index 9aa4fb77112..54d791b82d3 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/bigint.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/bigint.md @@ -48,7 +48,10 @@ The available operations for each big integer are: Construct a big integer from its little-endian bytes representation. Example: ```rust + // Construct a big integer from a slice of bytes let a = Secpk1Fq::from_le_bytes(&[x, y, 0, 45, 2]); + // Construct a big integer from an array of 32 bytes + let a = Secpk1Fq::from_le_bytes_32([1;32]); ``` Sure, here's the formatted version of the remaining methods: diff --git a/noir/noir-repo/docs/docs/getting_started/tooling/_category_.json b/noir/noir-repo/docs/docs/reference/debugger/_category_.json similarity index 53% rename from noir/noir-repo/docs/docs/getting_started/tooling/_category_.json rename to noir/noir-repo/docs/docs/reference/debugger/_category_.json index 55804c03a71..27869205ad3 100644 --- a/noir/noir-repo/docs/docs/getting_started/tooling/_category_.json +++ b/noir/noir-repo/docs/docs/reference/debugger/_category_.json @@ -1,6 +1,6 @@ { - "position": 2, - "label": "Tooling", + "label": "Debugger", + "position": 1, "collapsible": true, "collapsed": true } diff --git a/noir/noir-repo/docs/docs/reference/debugger/debugger_known_limitations.md b/noir/noir-repo/docs/docs/reference/debugger/debugger_known_limitations.md new file mode 100644 index 00000000000..936d416ac4b --- /dev/null +++ b/noir/noir-repo/docs/docs/reference/debugger/debugger_known_limitations.md @@ -0,0 +1,59 @@ +--- +title: Known limitations +description: + An overview of known limitations of the current version of the Noir debugger +keywords: + [ + Nargo, + Noir Debugger, + VS Code, + ] +sidebar_position: 2 +--- + +# Debugger Known Limitations + +There are currently some limits to what the debugger can observe. + +## Mutable references + +The debugger is currently blind to any state mutated via a mutable reference. For example, in: + +``` +let mut x = 1; +let y = &mut x; +*y = 2; +``` + +The update on `x` will not be observed by the debugger. That means, when running `vars` from the debugger REPL, or inspecting the _local variables_ pane in the VS Code debugger, `x` will appear with value 1 despite having executed `*y = 2;`. + +## Variables of type function or mutable references are opaque + +When inspecting variables, any variable of type `Function` or `MutableReference` will render its value as `<>` or `<>`. + +## Debugger instrumentation affects resulting ACIR + +In order to make the state of local variables observable, the debugger compiles Noir circuits interleaving foreign calls that track any mutations to them. While this works (except in the cases described above) and doesn't introduce any behavior changes, it does as a side effect produce bigger bytecode. In particular, when running the command `opcodes` on the REPL debugger, you will notice Unconstrained VM blocks that look like this: + +``` +... +5 BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [], q_c: 2 }), Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(2))], q_c: 0 })] + | outputs=[] + 5.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 5.1 | Mov { destination: RegisterIndex(3), source: RegisterIndex(1) } + 5.2 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 5.3 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 5.4 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 5.5 | Mov { destination: RegisterIndex(3), source: RegisterIndex(3) } + 5.6 | Call { location: 8 } + 5.7 | Stop + 5.8 | ForeignCall { function: "__debug_var_assign", destinations: [], inputs: [RegisterIndex(RegisterIndex(2)), RegisterIndex(RegisterIndex(3))] } +... +``` + +If you are interested in debugging/inspecting compiled ACIR without these synthetic changes, you can invoke the REPL debugger with the `--skip-instrumentation` flag or launch the VS Code debugger with the `skipConfiguration` property set to true in its launch configuration. You can find more details about those in the [Debugger REPL reference](debugger_repl.md) and the [VS Code Debugger reference](debugger_vscode.md). + +:::note +Skipping debugger instrumentation means you won't be able to inspect values of local variables. +::: + diff --git a/noir/noir-repo/docs/docs/reference/debugger/debugger_repl.md b/noir/noir-repo/docs/docs/reference/debugger/debugger_repl.md new file mode 100644 index 00000000000..46e2011304e --- /dev/null +++ b/noir/noir-repo/docs/docs/reference/debugger/debugger_repl.md @@ -0,0 +1,360 @@ +--- +title: REPL Debugger +description: + Noir Debugger REPL options and commands. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + REPL, + ] +sidebar_position: 1 +--- + +## Running the REPL debugger + +`nargo debug [OPTIONS] [WITNESS_NAME]` + +Runs the Noir REPL debugger. If a `WITNESS_NAME` is provided the debugger writes the resulting execution witness to a `WITNESS_NAME` file. + +### Options + +| Option | Description | +| --------------------- | ------------------------------------------------------------ | +| `-p, --prover-name ` | The name of the toml file which contains the inputs for the prover [default: Prover]| +| `--package ` | The name of the package to debug | +| `--print-acir` | Display the ACIR for compiled circuit | +| `--deny-warnings` | Treat all warnings as errors | +| `--silence-warnings` | Suppress warnings | +| `-h, --help` | Print help | + +None of these options are required. + +:::note +Since the debugger starts by compiling the target package, all Noir compiler options are also available. Check out the [compiler reference](../nargo_commands.md#nargo-compile) to learn more about the compiler options. +::: + +## REPL commands + +Once the debugger is running, it accepts the following commands. + +#### `help` (h) + +Displays the menu of available commands. + +``` +> help +Available commands: + + opcodes display ACIR opcodes + into step into to the next opcode + next step until a new source location is reached + out step until a new source location is reached + and the current stack frame is finished + break LOCATION:OpcodeLocation add a breakpoint at an opcode location + over step until a new source location is reached + without diving into function calls + restart restart the debugging session + delete LOCATION:OpcodeLocation delete breakpoint at an opcode location + witness show witness map + witness index:u32 display a single witness from the witness map + witness index:u32 value:String update a witness with the given value + memset index:usize value:String update a memory cell with the given + value + continue continue execution until the end of the + program + vars show variable values available at this point + in execution + stacktrace display the current stack trace + memory show memory (valid when executing unconstrained code) value + step step to the next ACIR opcode + +Other commands: + + help Show this help message + quit Quit repl + +``` + +### Stepping through programs + +#### `next` (n) + +Step until the next Noir source code location. While other commands, such as [`into`](#into-i) and [`step`](#step-s), allow for finer grained control of the program's execution at the opcode level, `next` is source code centric. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `next` here would cause the debugger to jump to the definition of `deep_entry_point` (if available). + +If you want to step over `deep_entry_point` and go straight to line 8, use [the `over` command](#over) instead. + +#### `over` + +Step until the next source code location, without diving into function calls. For example: + +``` +3 ... +4 fn main(x: u32) { +5 assert(entry_point(x) == 2); +6 swap_entry_point(x, x + 1); +7 -> assert(deep_entry_point(x) == 4); +8 multiple_values_entry_point(x); +9 } +``` + + +Using `over` here would cause the debugger to execute until line 8 (`multiple_values_entry_point(x);`). + +If you want to step into `deep_entry_point` instead, use [the `next` command](#next-n). + +#### `out` + +Step until the end of the current function call. For example: + +``` + 3 ... + 4 fn main(x: u32) { + 5 assert(entry_point(x) == 2); + 6 swap_entry_point(x, x + 1); + 7 -> assert(deep_entry_point(x) == 4); + 8 multiple_values_entry_point(x); + 9 } + 10 + 11 unconstrained fn returns_multiple_values(x: u32) -> (u32, u32, u32, u32) { + 12 ... + ... + 55 + 56 unconstrained fn deep_entry_point(x: u32) -> u32 { + 57 -> level_1(x + 1) + 58 } + +``` + +Running `out` here will resume execution until line 8. + +#### `step` (s) + +Skips to the next ACIR code. A compiled Noir program is a sequence of ACIR opcodes. However, an unconstrained VM opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `step` command at this point would result in the debugger stopping at ACIR opcode 2, `EXPR`, skipping unconstrained computation steps. + +Use [the `into` command](#into-i) instead if you want to follow unconstrained computation step by step. + +#### `into` (i) + +Steps into the next opcode. A compiled Noir program is a sequence of ACIR opcodes. However, a BRILLIG opcode denotes the start of an unconstrained code block, to be executed by the unconstrained VM. For example (redacted for brevity): + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +The `->` here shows the debugger paused at an ACIR opcode: `BRILLIG`, at index 1, which denotes an unconstrained code block is about to start. + +Using the `into` command at this point would result in the debugger stopping at opcode 1.0, `Mov ...`, allowing the debugger user to follow unconstrained computation step by step. + +Use [the `step` command](#step-s) instead if you want to skip to the next ACIR code directly. + +#### `continue` (c) + +Continues execution until the next breakpoint, or the end of the program. + +#### `restart` (res) + +Interrupts execution, and restarts a new debugging session from scratch. + +#### `opcodes` (o) + +Display the program's ACIR opcode sequence. For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +### Breakpoints + +#### `break [Opcode]` (or shorthand `b [Opcode]`) + +Sets a breakpoint on the specified opcode index. To get a list of the program opcode numbers, see [the `opcode` command](#opcodes-o). For example: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +In this example, issuing a `break 1.2` command adds break on opcode 1.2, as denoted by the `*` character: + +``` +0 BLACKBOX::RANGE [(_0, num_bits: 32)] [ ] +1 -> BRILLIG inputs=[Single(Expression { mul_terms: [], linear_combinations: [(1, Witness(0))], q_c: 0 })] outputs=[Simple(Witness(1))] + 1.0 | Mov { destination: RegisterIndex(2), source: RegisterIndex(0) } + 1.1 | Const { destination: RegisterIndex(0), value: Value { inner: 0 } } + 1.2 | * Const { destination: RegisterIndex(1), value: Value { inner: 0 } } + 1.3 | Mov { destination: RegisterIndex(2), source: RegisterIndex(2) } + 1.4 | Call { location: 7 } + ... + 1.43 | Return +2 EXPR [ (1, _1) -2 ] +``` + +Running [the `continue` command](#continue-c) at this point would cause the debugger to execute the program until opcode 1.2. + +#### `delete [Opcode]` (or shorthand `d [Opcode]`) + +Deletes a breakpoint at an opcode location. Usage is analogous to [the `break` command](#). + +### Variable inspection + +#### vars + +Show variable values available at this point in execution. + +:::note +The ability to inspect variable values from the debugger depends on compilation to be run in a special debug instrumentation mode. This instrumentation weaves variable tracing code with the original source code. + +So variable value inspection comes at the expense of making the resulting ACIR bytecode bigger and harder to understand and optimize. + +If you find this compromise unacceptable, you can run the debugger with the flag `--skip-debug-instrumentation`. This will compile your circuit without any additional debug information, so the resulting ACIR bytecode will be identical to the one produced by standard Noir compilation. However, if you opt for this, the `vars` command will not be available while debugging. +::: + + +### Stacktrace + +#### `stacktrace` + +Displays the current stack trace. + + +### Witness map + +#### `witness` (w) + +Show witness map. For example: + +``` +_0 = 0 +_1 = 2 +_2 = 1 +``` + +#### `witness [Witness Index]` + +Display a single witness from the witness map. For example: + +``` +> witness 1 +_1 = 2 +``` + +#### `witness [Witness Index] [New value]` + +Overwrite the given index with a new value. For example: + +``` +> witness 1 3 +_1 = 3 +``` + + +### Unconstrained VM memory + +#### `memory` + +Show unconstrained VM memory state. For example: + +``` +> memory +At opcode 1.13: Store { destination_pointer: RegisterIndex(0), source: RegisterIndex(3) } +... +> registers +0 = 0 +1 = 10 +2 = 0 +3 = 1 +4 = 1 +5 = 2³² +6 = 1 +> into +At opcode 1.14: Const { destination: RegisterIndex(5), value: Value { inner: 1 } } +... +> memory +0 = 1 +> +``` + +In the example above: we start with clean memory, then step through a `Store` opcode which stores the value of register 3 (1) into the memory address stored in register 0 (0). Thus now `memory` shows memory address 0 contains value 1. + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: + +#### `memset [Memory address] [New value]` + +Update a memory cell with the given value. For example: + +``` +> memory +0 = 1 +> memset 0 2 +> memory +0 = 2 +> memset 1 4 +> memory +0 = 2 +1 = 4 +> +``` + +:::note +This command is only functional while the debugger is executing unconstrained code. +::: \ No newline at end of file diff --git a/noir/noir-repo/docs/docs/reference/debugger/debugger_vscode.md b/noir/noir-repo/docs/docs/reference/debugger/debugger_vscode.md new file mode 100644 index 00000000000..c027332b3b0 --- /dev/null +++ b/noir/noir-repo/docs/docs/reference/debugger/debugger_vscode.md @@ -0,0 +1,82 @@ +--- +title: VS Code Debugger +description: + VS Code Debugger configuration and features. +keywords: + [ + Nargo, + Noir CLI, + Noir Debugger, + VS Code, + IDE, + ] +sidebar_position: 0 +--- + +# VS Code Noir Debugger Reference + +The Noir debugger enabled by the vscode-noir extension ships with default settings such that the most common scenario should run without any additional configuration steps. + +These defaults can nevertheless be overridden by defining a launch configuration file. This page provides a reference for the properties you can override via a launch configuration file, as well as documenting the Nargo `dap` command, which is a dependency of the VS Code Noir debugger. + + +## Creating and editing launch configuration files + +To create a launch configuration file from VS Code, open the _debug pane_, and click on _create a launch.json file_. + +![Creating a launch configuration file](@site/static/img/debugger/ref1-create-launch.png) + +A `launch.json` file will be created, populated with basic defaults. + +### Noir Debugger launch.json properties + +#### projectFolder + +_String, optional._ + +Absolute path to the Nargo project to debug. By default, it is dynamically determined by looking for the nearest `Nargo.toml` file to the active file at the moment of launching the debugger. + +#### proverName + +_String, optional._ + +Name of the prover input to use. Defaults to `Prover`, which looks for a file named `Prover.toml` at the `projectFolder`. + +#### generateAcir + +_Boolean, optional._ + +If true, generate ACIR opcodes instead of unconstrained opcodes which will be closer to release binaries but less convenient for debugging. Defaults to `false`. + +#### skipInstrumentation + +_Boolean, optional._ + +Skips variables debugging instrumentation of code, making debugging less convenient but the resulting binary smaller and closer to production. Defaults to `false`. + +:::note +Skipping instrumentation causes the debugger to be unable to inspect local variables. +::: + +## `nargo dap [OPTIONS]` + +When run without any option flags, it starts the Nargo Debug Adapter Protocol server, which acts as the debugging backend for the VS Code Noir Debugger. + +All option flags are related to preflight checks. The Debug Adapter Protocol specifies how errors are to be informed from a running DAP server, but it doesn't specify mechanisms to communicate server initialization errors between the DAP server and its client IDE. + +Thus `nargo dap` ships with a _preflight check_ mode. If flag `--preflight-check` and the rest of the `--preflight-*` flags are provided, Nargo will run the same initialization routine except it will not start the DAP server. + +`vscode-noir` will then run `nargo dap` in preflight check mode first before a debugging session starts. If the preflight check ends in error, vscode-noir will present stderr and stdout output from this process through its own Output pane in VS Code. This makes it possible for users to diagnose what pieces of configuration might be wrong or missing in case of initialization errors. + +If the preflight check succeeds, `vscode-noir` proceeds to start the DAP server normally but running `nargo dap` without any additional flags. + +### Options + +| Option | Description | +| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| `--preflight-check` | If present, dap runs in preflight check mode. | +| `--preflight-project-folder ` | Absolute path to the project to debug for preflight check. | +| `--preflight-prover-name ` | Name of prover file to use for preflight check | +| `--preflight-generate-acir` | Optional. If present, compile in ACIR mode while running preflight check. | +| `--preflight-skip-instrumentation` | Optional. If present, compile without introducing debug instrumentation while running preflight check. | +| `-h, --help` | Print help. | diff --git a/noir/noir-repo/docs/docs/tooling/debugger.md b/noir/noir-repo/docs/docs/tooling/debugger.md new file mode 100644 index 00000000000..184c436068f --- /dev/null +++ b/noir/noir-repo/docs/docs/tooling/debugger.md @@ -0,0 +1,27 @@ +--- +title: Debugger +description: Learn about the Noir Debugger, in its REPL or VS Code versions. +keywords: [Nargo, VSCode, Visual Studio Code, REPL, Debugger] +sidebar_position: 2 +--- + +# Noir Debugger + +There are currently two ways of debugging Noir programs: + +1. From VS Code, via the [vscode-noir](https://github.com/noir-lang/vscode-noir) extension. You can install it via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=noir-lang.vscode-noir). +2. Via the REPL debugger, which ships with Nargo. + +In order to use either version of the debugger, you will need to install recent enough versions of Noir, [Nargo](../getting_started/installation) and vscode-noir: + +- Noir 0.xx +- Nargo 0.xx +- vscode-noir 0.xx + +:::info +At the moment, the debugger supports debugging binary projects, but not contracts. +::: + +We cover the VS Code Noir debugger more in depth in [its VS Code debugger how-to guide](../how_to/debugger/debugging_with_vs_code.md) and [the reference](../reference/debugger/debugger_vscode.md). + +The REPL debugger is discussed at length in [the REPL debugger how-to guide](../how_to/debugger/debugging_with_the_repl.md) and [the reference](../reference/debugger/debugger_repl.md). diff --git a/noir/noir-repo/docs/docs/getting_started/tooling/language_server.md b/noir/noir-repo/docs/docs/tooling/language_server.md similarity index 100% rename from noir/noir-repo/docs/docs/getting_started/tooling/language_server.md rename to noir/noir-repo/docs/docs/tooling/language_server.md diff --git a/noir/noir-repo/docs/docs/getting_started/tooling/testing.md b/noir/noir-repo/docs/docs/tooling/testing.md similarity index 100% rename from noir/noir-repo/docs/docs/getting_started/tooling/testing.md rename to noir/noir-repo/docs/docs/tooling/testing.md diff --git a/noir/noir-repo/docs/sidebars.js b/noir/noir-repo/docs/sidebars.js index f1e79ba9ebc..cf7e852fed5 100644 --- a/noir/noir-repo/docs/sidebars.js +++ b/noir/noir-repo/docs/sidebars.js @@ -65,6 +65,11 @@ export default { label: 'Reference', items: [{ type: 'autogenerated', dirName: 'reference' }], }, + { + type: 'category', + label: 'Tooling', + items: [{ type: 'autogenerated', dirName: 'tooling' }], + }, { type: 'html', value: '
', diff --git a/noir/noir-repo/docs/static/img/debugger/1-started.png b/noir/noir-repo/docs/static/img/debugger/1-started.png new file mode 100644 index 00000000000..6f764d4e601 Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/1-started.png differ diff --git a/noir/noir-repo/docs/static/img/debugger/2-icon.png b/noir/noir-repo/docs/static/img/debugger/2-icon.png new file mode 100644 index 00000000000..31706670ccb Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/2-icon.png differ diff --git a/noir/noir-repo/docs/static/img/debugger/3-debug-pane.png b/noir/noir-repo/docs/static/img/debugger/3-debug-pane.png new file mode 100644 index 00000000000..24c112da96f Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/3-debug-pane.png differ diff --git a/noir/noir-repo/docs/static/img/debugger/4-debugger-buttons.png b/noir/noir-repo/docs/static/img/debugger/4-debugger-buttons.png new file mode 100644 index 00000000000..64c1e05be8a Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/4-debugger-buttons.png differ diff --git a/noir/noir-repo/docs/static/img/debugger/5-assert.png b/noir/noir-repo/docs/static/img/debugger/5-assert.png new file mode 100644 index 00000000000..0bfed6562af Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/5-assert.png differ diff --git a/noir/noir-repo/docs/static/img/debugger/6-hover.png b/noir/noir-repo/docs/static/img/debugger/6-hover.png new file mode 100644 index 00000000000..20579ec461e Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/6-hover.png differ diff --git a/noir/noir-repo/docs/static/img/debugger/7-break.png b/noir/noir-repo/docs/static/img/debugger/7-break.png new file mode 100644 index 00000000000..aca5121d722 Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/7-break.png differ diff --git a/noir/noir-repo/docs/static/img/debugger/debugger-intro.gif b/noir/noir-repo/docs/static/img/debugger/debugger-intro.gif new file mode 100644 index 00000000000..06e3b853555 Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/debugger-intro.gif differ diff --git a/noir/noir-repo/docs/static/img/debugger/ref1-create-launch.png b/noir/noir-repo/docs/static/img/debugger/ref1-create-launch.png new file mode 100644 index 00000000000..0b6cb8b3ec6 Binary files /dev/null and b/noir/noir-repo/docs/static/img/debugger/ref1-create-launch.png differ diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md index d9ac92667c9..8168793fc80 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.17.0/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md index d9ac92667c9..8168793fc80 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.0/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md index d9ac92667c9..8168793fc80 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.1/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md index d9ac92667c9..8168793fc80 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.2/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md index a979ef9f0a5..8168793fc80 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.3/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: @@ -36,4 +38,4 @@ default-member = "crates/a" Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. \ No newline at end of file +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md index a979ef9f0a5..8168793fc80 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.19.4/modules_packages_crates/workspaces.md @@ -10,16 +10,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: @@ -36,4 +38,4 @@ default-member = "crates/a" Libraries can be defined in a workspace. Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. -Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. \ No newline at end of file +Inside a workspace, these are consumed as `{ path = "../to_lib" }` dependencies in Nargo.toml. diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.22.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.23.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.24.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.25.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.26.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md index 67a1dafa372..513497f12bf 100644 --- a/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md +++ b/noir/noir-repo/docs/versioned_docs/version-v0.27.0/noir/modules_packages_crates/workspaces.md @@ -11,16 +11,18 @@ For a project with the following structure: ```tree ├── crates -│   ├── a -│   │   ├── Nargo.toml -│   │   └── src -│   │   └── main.nr -│   └── b -│   ├── Nargo.toml -│   └── src -│   └── main.nr -├── Nargo.toml -└── Prover.toml +│ ├── a +│ │ ├── Nargo.toml +│ │ └── Prover.toml +│ │ └── src +│ │ └── main.nr +│ └── b +│ ├── Nargo.toml +│ └── Prover.toml +│ └── src +│ └── main.nr +│ +└── Nargo.toml ``` You can define a workspace in Nargo.toml like so: diff --git a/noir/noir-repo/noir_stdlib/src/bigint.nr b/noir/noir-repo/noir_stdlib/src/bigint.nr index 39ec40a1480..ee9f8e44625 100644 --- a/noir/noir-repo/noir_stdlib/src/bigint.nr +++ b/noir/noir-repo/noir_stdlib/src/bigint.nr @@ -32,7 +32,7 @@ impl BigInt { #[builtin(bigint_from_le_bytes)] fn from_le_bytes(bytes: [u8], modulus: [u8]) -> BigInt {} #[builtin(bigint_to_le_bytes)] - fn to_le_bytes(self) -> [u8] {} + fn to_le_bytes(self) -> [u8; 32] {} fn check_32_bytes(self: Self, other: BigInt) -> bool { let bytes = self.to_le_bytes(); @@ -47,305 +47,420 @@ impl BigInt { trait BigField { fn from_le_bytes(bytes: [u8]) -> Self; + fn from_le_bytes_32(bytes: [u8; 32]) -> Self; fn to_le_bytes(self) -> [u8]; } struct Secpk1Fq { - inner: BigInt, + array: [u8;32], } impl BigField for Secpk1Fq { fn from_le_bytes(bytes: [u8]) -> Secpk1Fq { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } + Secpk1Fq { + array: array, + } + } + + fn from_le_bytes_32(bytes: [u8;32]) -> Secpk1Fq { Secpk1Fq { - inner: BigInt::from_le_bytes(bytes, secpk1_fq) + array: bytes, } } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Secpk1Fq { fn add(self: Self, other: Secpk1Fq) -> Secpk1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fq { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Secpk1Fq { fn sub(self: Self, other: Secpk1Fq) -> Secpk1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fq { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Secpk1Fq { fn mul(self: Self, other: Secpk1Fq) -> Secpk1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fq { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Secpk1Fq { fn div(self: Self, other: Secpk1Fq) -> Secpk1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fq { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpk1Fq { fn eq(self: Self, other: Secpk1Fq) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Secpk1Fr { - inner: BigInt, + array: [u8;32], } impl BigField for Secpk1Fr { fn from_le_bytes(bytes: [u8]) -> Secpk1Fr { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } Secpk1Fr { - inner: BigInt::from_le_bytes(bytes, secpk1_fr) + array: array, } } + + fn from_le_bytes_32(bytes: [u8;32]) -> Secpk1Fr { + Secpk1Fr { + array: bytes, + } + } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Secpk1Fr { fn add(self: Self, other: Secpk1Fr) -> Secpk1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fr { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Secpk1Fr { fn sub(self: Self, other: Secpk1Fr) -> Secpk1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fr { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Secpk1Fr { fn mul(self: Self, other: Secpk1Fr) -> Secpk1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fr { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Secpk1Fr { fn div(self: Self, other: Secpk1Fr) -> Secpk1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpk1Fr { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpk1Fr { fn eq(self: Self, other: Secpk1Fr) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Bn254Fr { - inner: BigInt, + array: [u8;32], } impl BigField for Bn254Fr { fn from_le_bytes(bytes: [u8]) -> Bn254Fr { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } + Bn254Fr { + array: array, + } + } + + fn from_le_bytes_32(bytes: [u8;32]) -> Bn254Fr { Bn254Fr { - inner: BigInt::from_le_bytes(bytes, bn254_fr) + array: bytes, } } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Bn254Fr { fn add(self: Self, other: Bn254Fr) -> Bn254Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Bn254Fr { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Bn254Fr { fn sub(self: Self, other: Bn254Fr) -> Bn254Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Bn254Fr { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Bn254Fr { fn mul(self: Self, other: Bn254Fr) -> Bn254Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Bn254Fr { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Bn254Fr { fn div(self: Self, other: Bn254Fr) -> Bn254Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Bn254Fr { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Bn254Fr { fn eq(self: Self, other: Bn254Fr) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Bn254Fq { - inner: BigInt, + array: [u8;32], } impl BigField for Bn254Fq { fn from_le_bytes(bytes: [u8]) -> Bn254Fq { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } Bn254Fq { - inner: BigInt::from_le_bytes(bytes, bn254_fq) + array: array, } } + + fn from_le_bytes_32(bytes: [u8;32]) -> Bn254Fq { + Bn254Fq { + array: bytes, + } + } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Bn254Fq { fn add(self: Self, other: Bn254Fq) -> Bn254Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Bn254Fq { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Bn254Fq { fn sub(self: Self, other: Bn254Fq) -> Bn254Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Bn254Fq { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Bn254Fq { fn mul(self: Self, other: Bn254Fq) -> Bn254Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Bn254Fq { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Bn254Fq { fn div(self: Self, other: Bn254Fq) -> Bn254Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Bn254Fq { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Bn254Fq { fn eq(self: Self, other: Bn254Fq) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Secpr1Fq { - inner: BigInt, + array: [u8;32], } impl BigField for Secpr1Fq { fn from_le_bytes(bytes: [u8]) -> Secpr1Fq { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } + Secpr1Fq { + array: array, + } + } + + fn from_le_bytes_32(bytes: [u8;32]) -> Secpr1Fq { Secpr1Fq { - inner: BigInt::from_le_bytes(bytes, secpr1_fq) + array: bytes, } } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Secpr1Fq { fn add(self: Self, other: Secpr1Fq) -> Secpr1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpr1Fq { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Secpr1Fq { fn sub(self: Self, other: Secpr1Fq) -> Secpr1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpr1Fq { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Secpr1Fq { fn mul(self: Self, other: Secpr1Fq) -> Secpr1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpr1Fq { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Secpr1Fq { fn div(self: Self, other: Secpr1Fq) -> Secpr1Fq { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpr1Fq { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpr1Fq { fn eq(self: Self, other: Secpr1Fq) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } struct Secpr1Fr { - inner: BigInt, + array: [u8;32], } impl BigField for Secpr1Fr { fn from_le_bytes(bytes: [u8]) -> Secpr1Fr { + assert(bytes.len() <= 32); + let mut array = [0;32]; + for i in 0..bytes.len() { + array[i] = bytes[i]; + } + Secpr1Fr { + array: array, + } + } + + fn from_le_bytes_32(bytes: [u8;32]) -> Secpr1Fr { Secpr1Fr { - inner: BigInt::from_le_bytes(bytes, secpr1_fr) + array: bytes, } } + fn to_le_bytes(self) -> [u8] { - self.inner.to_le_bytes() + self.array } } impl Add for Secpr1Fr { fn add(self: Self, other: Secpr1Fr) -> Secpr1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpr1Fr { - inner: self.inner.bigint_add(other.inner) + array: a.bigint_add(b).to_le_bytes() } } } impl Sub for Secpr1Fr { fn sub(self: Self, other: Secpr1Fr) -> Secpr1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpr1Fr { - inner: self.inner.bigint_sub(other.inner) + array: a.bigint_sub(b).to_le_bytes() } } } impl Mul for Secpr1Fr { fn mul(self: Self, other: Secpr1Fr) -> Secpr1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpr1Fr { - inner: self.inner.bigint_mul(other.inner) + array: a.bigint_mul(b).to_le_bytes() } - } } impl Div for Secpr1Fr { fn div(self: Self, other: Secpr1Fr) -> Secpr1Fr { + let a = BigInt::from_le_bytes(self.array.as_slice(), secpk1_fq); + let b = BigInt::from_le_bytes(other.array.as_slice(), secpk1_fq); Secpr1Fr { - inner: self.inner.bigint_div(other.inner) + array: a.bigint_div(b).to_le_bytes() } } } impl Eq for Secpr1Fr { fn eq(self: Self, other: Secpr1Fr) -> bool { - self.inner.check_32_bytes(other.inner) + self.array == other.array } } diff --git a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr index 6d5fbd44247..c789bc386ef 100644 --- a/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr +++ b/noir/noir-repo/noir_stdlib/src/collections/bounded_vec.nr @@ -10,7 +10,7 @@ impl BoundedVec { } pub fn get(mut self: Self, index: u64) -> T { - assert(index as u64 < self.len); + assert(index < self.len); self.storage[index] } @@ -19,7 +19,7 @@ impl BoundedVec { } pub fn push(&mut self, elem: T) { - assert(self.len < MaxLen as u64, "push out of bounds"); + assert(self.len < MaxLen, "push out of bounds"); self.storage[self.len] = elem; self.len += 1; @@ -41,7 +41,7 @@ impl BoundedVec { pub fn extend_from_array(&mut self, array: [T; Len]) { let new_len = self.len + array.len(); - assert(new_len as u64 <= MaxLen as u64, "extend_from_array out of bounds"); + assert(new_len <= MaxLen, "extend_from_array out of bounds"); for i in 0..array.len() { self.storage[self.len + i] = array[i]; } @@ -50,7 +50,7 @@ impl BoundedVec { pub fn extend_from_slice(&mut self, slice: [T]) { let new_len = self.len + slice.len(); - assert(new_len as u64 <= MaxLen as u64, "extend_from_slice out of bounds"); + assert(new_len <= MaxLen, "extend_from_slice out of bounds"); for i in 0..slice.len() { self.storage[self.len + i] = slice[i]; } @@ -60,7 +60,7 @@ impl BoundedVec { pub fn extend_from_bounded_vec(&mut self, vec: BoundedVec) { let append_len = vec.len(); let new_len = self.len + append_len; - assert(new_len as u64 <= MaxLen as u64, "extend_from_bounded_vec out of bounds"); + assert(new_len <= MaxLen, "extend_from_bounded_vec out of bounds"); let mut exceeded_len = false; for i in 0..Len { @@ -73,7 +73,7 @@ impl BoundedVec { } pub fn pop(&mut self) -> T { - assert(self.len as u64 > 0); + assert(self.len > 0); self.len -= 1; let elem = self.storage[self.len]; diff --git a/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/Nargo.toml new file mode 100644 index 00000000000..e49a82cf0fb --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_dyn_index_fail" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/Prover.toml b/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/Prover.toml new file mode 100644 index 00000000000..caf3448c56f --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/Prover.toml @@ -0,0 +1,2 @@ +x = [104, 101, 108, 108, 111] +z = "4" diff --git a/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/src/main.nr b/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/src/main.nr new file mode 100644 index 00000000000..b12dea630b0 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/fold_dyn_index_fail/src/main.nr @@ -0,0 +1,10 @@ +fn main(mut x: [u32; 5], z: Field) { + x[z] = 4; + dynamic_index_check(x, z + 10); +} + +#[fold] +fn dynamic_index_check(x: [u32; 5], idx: Field) { + // Dynamic index is greater than length of the array + assert(x[idx] != 0); +} diff --git a/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/Nargo.toml new file mode 100644 index 00000000000..bb7d5e20dcc --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_nested_brillig_assert_fail" +type = "bin" +authors = [""] +compiler_version = ">=0.26.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/Prover.toml b/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/Prover.toml new file mode 100644 index 00000000000..11497a473bc --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/Prover.toml @@ -0,0 +1 @@ +x = "0" diff --git a/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/src/main.nr b/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/src/main.nr new file mode 100644 index 00000000000..0a5038c179b --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/fold_nested_brillig_assert_fail/src/main.nr @@ -0,0 +1,26 @@ +// Tests a very simple program. +// +// The features being tested is using assert on brillig that is triggered through nested ACIR calls. +// We want to make sure we get a call stack from the original call in main to the failed assert. +fn main(x: Field) { + assert(1 == fold_conditional_wrapper(x as bool)); +} + +#[fold] +fn fold_conditional_wrapper(x: bool) -> Field { + fold_conditional(x) +} + +#[fold] +fn fold_conditional(x: bool) -> Field { + conditional_wrapper(x) +} + +unconstrained fn conditional_wrapper(x: bool) -> Field { + conditional(x) +} + +unconstrained fn conditional(x: bool) -> Field { + assert(x); + 1 +} diff --git a/noir/noir-repo/test_programs/execution_success/bigint/src/main.nr b/noir/noir-repo/test_programs/execution_success/bigint/src/main.nr index db269d63ac0..5645e4e9e1b 100644 --- a/noir/noir-repo/test_programs/execution_success/bigint/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/bigint/src/main.nr @@ -4,17 +4,51 @@ use dep::std::{bigint::Secpk1Fq, println}; fn main(mut x: [u8; 5], y: [u8; 5]) { let a = bigint::Secpk1Fq::from_le_bytes(&[x[0], x[1], x[2], x[3], x[4]]); let b = bigint::Secpk1Fq::from_le_bytes(&[y[0], y[1], y[2], y[3], y[4]]); + let mut a_be_bytes = [0; 32]; + let mut b_be_bytes = [0; 32]; + for i in 0..5 { + a_be_bytes[31-i] = x[i]; + b_be_bytes[31-i] = y[i]; + } + let a_field = dep::std::field::bytes32_to_field(a_be_bytes); + let b_field = dep::std::field::bytes32_to_field(b_be_bytes); + + // Regression for #4682 + let c = if x[0] != 0 { + test_unconstrained1(a, b) + } else { + test_unconstrained2(a, b) + }; + assert(c.array[0] == dep::std::wrapping_mul(x[0], y[0])); + let a_bytes = a.to_le_bytes(); let b_bytes = b.to_le_bytes(); for i in 0..5 { assert(a_bytes[i] == x[i]); assert(b_bytes[i] == y[i]); } + //Regression for issue #4578 + let d = a * b; + assert(d / b == a); - let d = a * b - b; - let d1 = bigint::Secpk1Fq::from_le_bytes(597243850900842442924.to_le_bytes(10)); + let d = d - b; + let mut result = [0; 32]; + let result_slice = (a_field * b_field - b_field).to_le_bytes(32); + for i in 0..32 { + result[i] = result_slice[i]; + } + let d1 = bigint::Secpk1Fq::from_le_bytes_32(result); assert(d1 == d); - // big_int_example(x[0], x[1]); + big_int_example(x[0], x[1]); +} + +fn test_unconstrained1(a: Secpk1Fq, b: Secpk1Fq) -> Secpk1Fq { + let c = a * b; + c +} +unconstrained fn test_unconstrained2(a: Secpk1Fq, b: Secpk1Fq) -> Secpk1Fq { + let c = a + b; + test_unconstrained1(a, c) } // docs:start:big_int_example diff --git a/noir/noir-repo/test_programs/execution_success/brillig_slice_input/src/main.nr b/noir/noir-repo/test_programs/execution_success/brillig_slice_input/src/main.nr index 09a9d9aef9d..8403cb7d4a0 100644 --- a/noir/noir-repo/test_programs/execution_success/brillig_slice_input/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/brillig_slice_input/src/main.nr @@ -25,6 +25,9 @@ fn main() { y: 8, } ]); + let brillig_sum = sum_slice(slice); + assert_eq(brillig_sum, 55); + slice = slice.push_back([ Point { x: 15, diff --git a/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml new file mode 100644 index 00000000000..d23924af083 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "fold_after_inlined_calls" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/workspace/Prover.toml b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Prover.toml similarity index 50% rename from noir/noir-repo/test_programs/execution_success/workspace/Prover.toml rename to noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Prover.toml index a0397e89477..4dd6b405159 100644 --- a/noir/noir-repo/test_programs/execution_success/workspace/Prover.toml +++ b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/Prover.toml @@ -1,2 +1 @@ x = "1" -y = "0" diff --git a/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/src/main.nr b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/src/main.nr new file mode 100644 index 00000000000..84c81190b9b --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/fold_after_inlined_calls/src/main.nr @@ -0,0 +1,14 @@ +fn main(x: u32) { + // We want to call a foldable function after a call to a function that is set to be inlined + assert(increment(x) == x + 1); + foo(x); +} + +#[fold] +fn foo(x: u32) { + assert(x == 1); +} + +fn increment(x: u32) -> u32 { + x + 1 +} diff --git a/noir/noir-repo/test_programs/execution_success/unit_value/Nargo.toml b/noir/noir-repo/test_programs/execution_success/unit_value/Nargo.toml new file mode 100644 index 00000000000..f7e3697a7c1 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/unit_value/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "short" +type = "bin" +authors = [""] +compiler_version = ">=0.23.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/unit_value/src/main.nr b/noir/noir-repo/test_programs/execution_success/unit_value/src/main.nr new file mode 100644 index 00000000000..f3844e03cf2 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/unit_value/src/main.nr @@ -0,0 +1,7 @@ +fn get_transaction() { + dep::std::unsafe::zeroed() +} + +fn main() { + get_transaction(); +} diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index b211832518d..9b535075484 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -1,4 +1,5 @@ use crate::foreign_calls::DebugForeignCallExecutor; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap}; use acvm::brillig_vm::brillig::ForeignCallResult; @@ -42,10 +43,17 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, foreign_call_executor: Box, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { let source_to_opcodes = build_source_to_opcode_debug_mappings(debug_artifact); Self { - acvm: ACVM::new(blackbox_solver, &circuit.opcodes, initial_witness), + // TODO: need to handle brillig pointer in the debugger + acvm: ACVM::new( + blackbox_solver, + &circuit.opcodes, + initial_witness, + unconstrained_functions, + ), brillig_solver: None, foreign_call_executor, debug_artifact, @@ -331,7 +339,8 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { self.handle_foreign_call(foreign_call) } Err(err) => DebugCommandResult::Error(NargoError::ExecutionError( - ExecutionError::SolvingError(err), + // TODO: debugger does not not handle multiple acir calls + ExecutionError::SolvingError(err, None), )), } } @@ -374,7 +383,8 @@ impl<'a, B: BlackBoxFunctionSolver> DebugContext<'a, B> { } } ACVMStatus::Failure(error) => DebugCommandResult::Error(NargoError::ExecutionError( - ExecutionError::SolvingError(error), + // TODO: debugger does not not handle multiple acir calls + ExecutionError::SolvingError(error, None), )), ACVMStatus::RequiresForeignCall(_) => { unreachable!("Unexpected pending foreign call resolution"); @@ -630,6 +640,7 @@ fn build_source_to_opcode_debug_mappings( result } +// TODO: update all debugger tests to use unconstrained brillig pointers #[cfg(test)] mod tests { use super::*; @@ -696,12 +707,14 @@ mod tests { let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)); + let brillig_funcs = &vec![]; let mut context = DebugContext::new( &StubbedBlackBoxSolver, circuit, debug_artifact, initial_witness, foreign_call_executor, + brillig_funcs, ); assert_eq!(context.get_current_opcode_location(), Some(OpcodeLocation::Acir(0))); @@ -803,12 +816,14 @@ mod tests { let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)); + let brillig_funcs = &vec![]; let mut context = DebugContext::new( &StubbedBlackBoxSolver, circuit, debug_artifact, initial_witness, foreign_call_executor, + brillig_funcs, ); // set breakpoint @@ -860,12 +875,14 @@ mod tests { let circuit = Circuit { opcodes, ..Circuit::default() }; let debug_artifact = DebugArtifact { debug_symbols: vec![], file_map: BTreeMap::new(), warnings: vec![] }; + let brillig_funcs = &vec![]; let context = DebugContext::new( &StubbedBlackBoxSolver, &circuit, &debug_artifact, WitnessMap::new(), Box::new(DefaultDebugForeignCallExecutor::new(true)), + brillig_funcs, ); assert_eq!(context.offset_opcode_location(&None, 0), (None, 0)); diff --git a/noir/noir-repo/tooling/debugger/src/dap.rs b/noir/noir-repo/tooling/debugger/src/dap.rs index ea3204ebbbc..060945132f5 100644 --- a/noir/noir-repo/tooling/debugger/src/dap.rs +++ b/noir/noir-repo/tooling/debugger/src/dap.rs @@ -2,6 +2,7 @@ use std::collections::BTreeMap; use std::io::{Read, Write}; use std::str::FromStr; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, OpcodeLocation}; use acvm::acir::native_types::WitnessMap; use acvm::BlackBoxFunctionSolver; @@ -64,6 +65,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { let context = DebugContext::new( solver, @@ -71,6 +73,7 @@ impl<'a, R: Read, W: Write, B: BlackBoxFunctionSolver> DapSession<'a, R, W, B> { debug_artifact, initial_witness, Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)), + unconstrained_functions, ); Self { server, @@ -603,7 +606,7 @@ pub fn run_session( initial_witness: WitnessMap, ) -> Result<(), ServerError> { let debug_artifact = DebugArtifact { - debug_symbols: vec![program.debug], + debug_symbols: program.debug, file_map: program.file_map, warnings: program.warnings, }; @@ -613,6 +616,7 @@ pub fn run_session( &program.program.functions[0], &debug_artifact, initial_witness, + &program.program.unconstrained_functions, ); session.run_loop() diff --git a/noir/noir-repo/tooling/debugger/src/lib.rs b/noir/noir-repo/tooling/debugger/src/lib.rs index 4a25e3417a0..a8fc61c893f 100644 --- a/noir/noir-repo/tooling/debugger/src/lib.rs +++ b/noir/noir-repo/tooling/debugger/src/lib.rs @@ -9,6 +9,7 @@ use std::io::{Read, Write}; use ::dap::errors::ServerError; use ::dap::server::Server; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::BlackBoxFunctionSolver; use acvm::{acir::circuit::Circuit, acir::native_types::WitnessMap}; @@ -22,8 +23,9 @@ pub fn debug_circuit( circuit: &Circuit, debug_artifact: DebugArtifact, initial_witness: WitnessMap, + unconstrained_functions: &[BrilligBytecode], ) -> Result, NargoError> { - repl::run(blackbox_solver, circuit, &debug_artifact, initial_witness) + repl::run(blackbox_solver, circuit, &debug_artifact, initial_witness, unconstrained_functions) } pub fn run_dap_loop( diff --git a/noir/noir-repo/tooling/debugger/src/repl.rs b/noir/noir-repo/tooling/debugger/src/repl.rs index e30d519b62e..2a92698e5ce 100644 --- a/noir/noir-repo/tooling/debugger/src/repl.rs +++ b/noir/noir-repo/tooling/debugger/src/repl.rs @@ -1,5 +1,6 @@ use crate::context::{DebugCommandResult, DebugContext}; +use acvm::acir::circuit::brillig::BrilligBytecode; use acvm::acir::circuit::{Circuit, Opcode, OpcodeLocation}; use acvm::acir::native_types::{Witness, WitnessMap}; use acvm::{BlackBoxFunctionSolver, FieldElement}; @@ -20,6 +21,7 @@ pub struct ReplDebugger<'a, B: BlackBoxFunctionSolver> { debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, last_result: DebugCommandResult, + unconstrained_functions: &'a [BrilligBytecode], } impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { @@ -28,6 +30,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { circuit: &'a Circuit, debug_artifact: &'a DebugArtifact, initial_witness: WitnessMap, + unconstrained_functions: &'a [BrilligBytecode], ) -> Self { let foreign_call_executor = Box::new(DefaultDebugForeignCallExecutor::from_artifact(true, debug_artifact)); @@ -37,6 +40,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { debug_artifact, initial_witness.clone(), foreign_call_executor, + unconstrained_functions, ); let last_result = if context.get_current_opcode_location().is_none() { // handle circuit with no opcodes @@ -44,7 +48,15 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { } else { DebugCommandResult::Ok }; - Self { context, blackbox_solver, circuit, debug_artifact, initial_witness, last_result } + Self { + context, + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + last_result, + unconstrained_functions, + } } pub fn show_current_vm_status(&self) { @@ -271,6 +283,7 @@ impl<'a, B: BlackBoxFunctionSolver> ReplDebugger<'a, B> { self.debug_artifact, self.initial_witness.clone(), foreign_call_executor, + self.unconstrained_functions, ); for opcode_location in breakpoints { self.context.add_breakpoint(opcode_location); @@ -361,9 +374,15 @@ pub fn run( circuit: &Circuit, debug_artifact: &DebugArtifact, initial_witness: WitnessMap, + unconstrained_functions: &[BrilligBytecode], ) -> Result, NargoError> { - let context = - RefCell::new(ReplDebugger::new(blackbox_solver, circuit, debug_artifact, initial_witness)); + let context = RefCell::new(ReplDebugger::new( + blackbox_solver, + circuit, + debug_artifact, + initial_witness, + unconstrained_functions, + )); let ref_context = &context; ref_context.borrow().show_current_vm_status(); diff --git a/noir/noir-repo/tooling/lsp/src/requests/profile_run.rs b/noir/noir-repo/tooling/lsp/src/requests/profile_run.rs index 89719947689..7d06bc87c85 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/profile_run.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/profile_run.rs @@ -84,9 +84,11 @@ fn on_profile_run_request_inner( let compiled_program = nargo::ops::transform_program(compiled_program, expression_width); - let span_opcodes = compiled_program.debug.count_span_opcodes(); - let debug_artifact: DebugArtifact = compiled_program.clone().into(); - opcodes_counts.extend(span_opcodes); + for function_debug in compiled_program.debug.iter() { + let span_opcodes = function_debug.count_span_opcodes(); + opcodes_counts.extend(span_opcodes); + } + let debug_artifact: DebugArtifact = compiled_program.into(); file_map.extend(debug_artifact.file_map); } @@ -94,14 +96,17 @@ fn on_profile_run_request_inner( let compiled_contract = nargo::ops::transform_contract(compiled_contract, expression_width); - let function_debug_info: Vec<_> = - compiled_contract.functions.iter().map(|func| &func.debug).cloned().collect(); - let debug_artifact: DebugArtifact = compiled_contract.into(); - file_map.extend(debug_artifact.file_map); + let function_debug_info = compiled_contract + .functions + .iter() + .flat_map(|func| &func.debug) + .collect::>(); for contract_function_debug in function_debug_info { let span_opcodes = contract_function_debug.count_span_opcodes(); opcodes_counts.extend(span_opcodes); } + let debug_artifact: DebugArtifact = compiled_contract.into(); + file_map.extend(debug_artifact.file_map); } let result = NargoProfileRunResult { file_map, opcodes_counts }; diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs index 868fb4404fd..83bb4b94f82 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/contract.rs @@ -4,7 +4,7 @@ use noirc_driver::{CompiledContract, CompiledContractOutputs, ContractFunction}; use serde::{Deserialize, Serialize}; use noirc_driver::DebugFile; -use noirc_errors::debug_info::DebugInfo; +use noirc_errors::debug_info::ProgramDebugInfo; use std::collections::{BTreeMap, HashMap}; use fm::FileId; @@ -68,10 +68,10 @@ pub struct ContractFunctionArtifact { pub bytecode: Program, #[serde( - serialize_with = "DebugInfo::serialize_compressed_base64_json", - deserialize_with = "DebugInfo::deserialize_compressed_base64_json" + serialize_with = "ProgramDebugInfo::serialize_compressed_base64_json", + deserialize_with = "ProgramDebugInfo::deserialize_compressed_base64_json" )] - pub debug_symbols: DebugInfo, + pub debug_symbols: ProgramDebugInfo, } impl From for ContractFunctionArtifact { @@ -82,7 +82,7 @@ impl From for ContractFunctionArtifact { custom_attributes: func.custom_attributes, abi: func.abi, bytecode: func.bytecode, - debug_symbols: func.debug, + debug_symbols: ProgramDebugInfo { debug_infos: func.debug }, } } } diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs b/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs index fbdf59805c9..496896468cc 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/debug.rs @@ -121,7 +121,7 @@ impl DebugArtifact { impl From for DebugArtifact { fn from(compiled_program: CompiledProgram) -> Self { DebugArtifact { - debug_symbols: vec![compiled_program.debug], + debug_symbols: compiled_program.debug, file_map: compiled_program.file_map, warnings: compiled_program.warnings, } @@ -133,7 +133,7 @@ impl From for DebugArtifact { let all_functions_debug: Vec = compiled_artifact .functions .into_iter() - .map(|contract_function| contract_function.debug) + .flat_map(|contract_function| contract_function.debug) .collect(); DebugArtifact { diff --git a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs index 9e660cbd359..67ac9f53ec8 100644 --- a/noir/noir-repo/tooling/nargo/src/artifacts/program.rs +++ b/noir/noir-repo/tooling/nargo/src/artifacts/program.rs @@ -5,7 +5,7 @@ use fm::FileId; use noirc_abi::Abi; use noirc_driver::CompiledProgram; use noirc_driver::DebugFile; -use noirc_errors::debug_info::DebugInfo; +use noirc_errors::debug_info::ProgramDebugInfo; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] @@ -27,10 +27,10 @@ pub struct ProgramArtifact { pub bytecode: Program, #[serde( - serialize_with = "DebugInfo::serialize_compressed_base64_json", - deserialize_with = "DebugInfo::deserialize_compressed_base64_json" + serialize_with = "ProgramDebugInfo::serialize_compressed_base64_json", + deserialize_with = "ProgramDebugInfo::deserialize_compressed_base64_json" )] - pub debug_symbols: DebugInfo, + pub debug_symbols: ProgramDebugInfo, /// Map of file Id to the source code so locations in debug info can be mapped to source code they point to. pub file_map: BTreeMap, @@ -45,7 +45,7 @@ impl From for ProgramArtifact { abi: compiled_program.abi, noir_version: compiled_program.noir_version, bytecode: compiled_program.program, - debug_symbols: compiled_program.debug, + debug_symbols: ProgramDebugInfo { debug_infos: compiled_program.debug }, file_map: compiled_program.file_map, names: compiled_program.names, } @@ -59,7 +59,7 @@ impl From for CompiledProgram { abi: program.abi, noir_version: program.noir_version, program: program.bytecode, - debug: program.debug_symbols, + debug: program.debug_symbols.debug_infos, file_map: program.file_map, warnings: vec![], names: program.names, diff --git a/noir/noir-repo/tooling/nargo/src/errors.rs b/noir/noir-repo/tooling/nargo/src/errors.rs index f1e77d47a73..ac03330a7c8 100644 --- a/noir/noir-repo/tooling/nargo/src/errors.rs +++ b/noir/noir-repo/tooling/nargo/src/errors.rs @@ -1,5 +1,5 @@ use acvm::{ - acir::circuit::OpcodeLocation, + acir::circuit::{OpcodeLocation, ResolvedOpcodeLocation}, pwg::{ErrorLocation, OpcodeResolutionError}, }; use noirc_errors::{ @@ -61,7 +61,7 @@ impl NargoError { match execution_error { ExecutionError::AssertionFailed(message, _) => Some(message), - ExecutionError::SolvingError(error) => match error { + ExecutionError::SolvingError(error, _) => match error { OpcodeResolutionError::IndexOutOfBounds { .. } | OpcodeResolutionError::OpcodeNotSolvable(_) | OpcodeResolutionError::UnsatisfiedConstrain { .. } @@ -79,81 +79,105 @@ impl NargoError { #[derive(Debug, Error)] pub enum ExecutionError { #[error("Failed assertion: '{}'", .0)] - AssertionFailed(String, Vec), + AssertionFailed(String, Vec), - #[error(transparent)] - SolvingError(#[from] OpcodeResolutionError), + #[error("Failed to solve program: '{}'", .0)] + SolvingError(OpcodeResolutionError, Option>), } /// Extracts the opcode locations from a nargo error. fn extract_locations_from_error( error: &ExecutionError, - debug: &DebugInfo, + debug: &[DebugInfo], ) -> Option> { let mut opcode_locations = match error { - ExecutionError::SolvingError(OpcodeResolutionError::BrilligFunctionFailed { - call_stack, - .. - }) - | ExecutionError::AssertionFailed(_, call_stack) => Some(call_stack.clone()), - ExecutionError::SolvingError(OpcodeResolutionError::IndexOutOfBounds { - opcode_location: error_location, - .. - }) - | ExecutionError::SolvingError(OpcodeResolutionError::UnsatisfiedConstrain { - opcode_location: error_location, - }) => match error_location { + ExecutionError::SolvingError( + OpcodeResolutionError::BrilligFunctionFailed { .. }, + acir_call_stack, + ) => acir_call_stack.clone(), + ExecutionError::AssertionFailed(_, call_stack) => Some(call_stack.clone()), + ExecutionError::SolvingError( + OpcodeResolutionError::IndexOutOfBounds { opcode_location: error_location, .. }, + acir_call_stack, + ) + | ExecutionError::SolvingError( + OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: error_location }, + acir_call_stack, + ) => match error_location { ErrorLocation::Unresolved => { unreachable!("Cannot resolve index for unsatisfied constraint") } - ErrorLocation::Resolved(opcode_location) => Some(vec![*opcode_location]), + ErrorLocation::Resolved(_) => acir_call_stack.clone(), }, _ => None, }?; - if let Some(OpcodeLocation::Brillig { acir_index, .. }) = opcode_locations.first() { - opcode_locations.insert(0, OpcodeLocation::Acir(*acir_index)); + // Insert the top-level Acir location where the Brillig function failed + for (i, resolved_location) in opcode_locations.iter().enumerate() { + if let ResolvedOpcodeLocation { + acir_function_index, + opcode_location: OpcodeLocation::Brillig { acir_index, .. }, + } = resolved_location + { + let acir_location = ResolvedOpcodeLocation { + acir_function_index: *acir_function_index, + opcode_location: OpcodeLocation::Acir(*acir_index), + }; + + opcode_locations.insert(i, acir_location); + // Go until the first brillig opcode as that means we have the start of a Brillig call stack. + // We have to loop through the opcode locations in case we had ACIR calls + // before the brillig function failure. + break; + } } Some( opcode_locations .iter() - .flat_map(|opcode_location| debug.opcode_location(opcode_location).unwrap_or_default()) + .flat_map(|resolved_location| { + debug[resolved_location.acir_function_index] + .opcode_location(&resolved_location.opcode_location) + .unwrap_or_default() + }) .collect(), ) } -/// Tries to generate a runtime diagnostic from a nargo error. It will successfully do so if it's a runtime error with a call stack. -pub fn try_to_diagnose_runtime_error( - nargo_err: &NargoError, - debug: &DebugInfo, -) -> Option { - let execution_error = match nargo_err { - NargoError::ExecutionError(execution_error) => execution_error, - _ => return None, - }; - - let source_locations = extract_locations_from_error(execution_error, debug)?; - - // The location of the error itself will be the location at the top - // of the call stack (the last item in the Vec). - let location = source_locations.last()?; - - let message = match nargo_err { +fn extract_message_from_error(nargo_err: &NargoError) -> String { + match nargo_err { NargoError::ExecutionError(ExecutionError::AssertionFailed(message, _)) => { format!("Assertion failed: '{message}'") } NargoError::ExecutionError(ExecutionError::SolvingError( OpcodeResolutionError::IndexOutOfBounds { index, array_size, .. }, + _, )) => { format!("Index out of bounds, array has size {array_size:?}, but index was {index:?}") } NargoError::ExecutionError(ExecutionError::SolvingError( OpcodeResolutionError::UnsatisfiedConstrain { .. }, + _, )) => "Failed constraint".into(), _ => nargo_err.to_string(), - }; + } +} +/// Tries to generate a runtime diagnostic from a nargo error. It will successfully do so if it's a runtime error with a call stack. +pub fn try_to_diagnose_runtime_error( + nargo_err: &NargoError, + debug: &[DebugInfo], +) -> Option { + let source_locations = match nargo_err { + NargoError::ExecutionError(execution_error) => { + extract_locations_from_error(execution_error, debug)? + } + _ => return None, + }; + // The location of the error itself will be the location at the top + // of the call stack (the last item in the Vec). + let location = source_locations.last()?; + let message = extract_message_from_error(nargo_err); Some( CustomDiagnostic::simple_error(message, String::new(), location.span) .in_file(location.file) diff --git a/noir/noir-repo/tooling/nargo/src/ops/execute.rs b/noir/noir-repo/tooling/nargo/src/ops/execute.rs index 5ee0c6a3891..97584aff150 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/execute.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/execute.rs @@ -1,4 +1,5 @@ -use acvm::acir::circuit::Program; +use acvm::acir::circuit::brillig::BrilligBytecode; +use acvm::acir::circuit::{OpcodeLocation, Program, ResolvedOpcodeLocation}; use acvm::acir::native_types::WitnessStack; use acvm::brillig_vm::brillig::ForeignCallResult; use acvm::pwg::{ACVMStatus, ErrorLocation, OpcodeNotSolvable, OpcodeResolutionError, ACVM}; @@ -12,25 +13,41 @@ use super::foreign_calls::{ForeignCallExecutor, NargoForeignCallResult}; struct ProgramExecutor<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> { functions: &'a [Circuit], + + unconstrained_functions: &'a [BrilligBytecode], + // This gets built as we run through the program looking at each function call witness_stack: WitnessStack, blackbox_solver: &'a B, foreign_call_executor: &'a mut F, + + // The Noir compiler codegens per function and call stacks are not shared across ACIR function calls. + // We must rebuild a call stack when executing a program of many circuits. + call_stack: Vec, + + // Tracks the index of the current function we are executing. + // This is used to fetch the function we want to execute + // and to resolve call stack locations across many function calls. + current_function_index: usize, } impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, B, F> { fn new( functions: &'a [Circuit], + unconstrained_functions: &'a [BrilligBytecode], blackbox_solver: &'a B, foreign_call_executor: &'a mut F, ) -> Self { ProgramExecutor { functions, + unconstrained_functions, witness_stack: WitnessStack::default(), blackbox_solver, foreign_call_executor, + call_stack: Vec::default(), + current_function_index: 0, } } @@ -39,12 +56,14 @@ impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, } #[tracing::instrument(level = "trace", skip_all)] - fn execute_circuit( - &mut self, - circuit: &Circuit, - initial_witness: WitnessMap, - ) -> Result { - let mut acvm = ACVM::new(self.blackbox_solver, &circuit.opcodes, initial_witness); + fn execute_circuit(&mut self, initial_witness: WitnessMap) -> Result { + let circuit = &self.functions[self.current_function_index]; + let mut acvm = ACVM::new( + self.blackbox_solver, + &circuit.opcodes, + initial_witness, + self.unconstrained_functions, + ); // This message should be resolved by a nargo foreign call only when we have an unsatisfied assertion. let mut assert_message: Option = None; @@ -60,9 +79,26 @@ impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, let call_stack = match &error { OpcodeResolutionError::UnsatisfiedConstrain { opcode_location: ErrorLocation::Resolved(opcode_location), - } => Some(vec![*opcode_location]), + } + | OpcodeResolutionError::IndexOutOfBounds { + opcode_location: ErrorLocation::Resolved(opcode_location), + .. + } => { + let resolved_location = ResolvedOpcodeLocation { + acir_function_index: self.current_function_index, + opcode_location: *opcode_location, + }; + self.call_stack.push(resolved_location); + Some(self.call_stack.clone()) + } OpcodeResolutionError::BrilligFunctionFailed { call_stack, .. } => { - Some(call_stack.clone()) + let brillig_call_stack = + call_stack.iter().map(|location| ResolvedOpcodeLocation { + acir_function_index: self.current_function_index, + opcode_location: *location, + }); + self.call_stack.extend(brillig_call_stack); + Some(self.call_stack.clone()) } _ => None, }; @@ -85,17 +121,20 @@ impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, { ExecutionError::AssertionFailed(message.to_owned(), call_stack) } else if let Some(assert_message) = circuit.get_assert_message( - *call_stack.last().expect("Call stacks should not be empty"), + call_stack + .last() + .expect("Call stacks should not be empty") + .opcode_location, ) { ExecutionError::AssertionFailed( assert_message.to_owned(), call_stack, ) } else { - ExecutionError::SolvingError(error) + ExecutionError::SolvingError(error, Some(call_stack)) } } - None => ExecutionError::SolvingError(error), + None => ExecutionError::SolvingError(error, None), })); } ACVMStatus::RequiresForeignCall(foreign_call) => { @@ -115,10 +154,24 @@ impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, } } ACVMStatus::RequiresAcirCall(call_info) => { + // Store the parent function index whose context we are currently executing + let acir_function_caller = self.current_function_index; + // Add call opcode to the call stack with a reference to the parent function index + self.call_stack.push(ResolvedOpcodeLocation { + acir_function_index: acir_function_caller, + opcode_location: OpcodeLocation::Acir(acvm.instruction_pointer()), + }); + + // Set current function to the circuit we are about to execute + self.current_function_index = call_info.id as usize; + // Execute the ACIR call let acir_to_call = &self.functions[call_info.id as usize]; let initial_witness = call_info.initial_witness; - let call_solved_witness = - self.execute_circuit(acir_to_call, initial_witness)?; + let call_solved_witness = self.execute_circuit(initial_witness)?; + + // Set tracking index back to the parent function after ACIR call execution + self.current_function_index = acir_function_caller; + let mut call_resolved_outputs = Vec::new(); for return_witness_index in acir_to_call.return_values.indices() { if let Some(return_value) = @@ -128,6 +181,7 @@ impl<'a, B: BlackBoxFunctionSolver, F: ForeignCallExecutor> ProgramExecutor<'a, } else { return Err(ExecutionError::SolvingError( OpcodeNotSolvable::MissingAssignment(return_witness_index).into(), + None, // Missing assignment errors do not supply user-facing diagnostics so we do not need to attach a call stack ) .into()); } @@ -149,11 +203,13 @@ pub fn execute_program( blackbox_solver: &B, foreign_call_executor: &mut F, ) -> Result { - let main = &program.functions[0]; - - let mut executor = - ProgramExecutor::new(&program.functions, blackbox_solver, foreign_call_executor); - let main_witness = executor.execute_circuit(main, initial_witness)?; + let mut executor = ProgramExecutor::new( + &program.functions, + &program.unconstrained_functions, + blackbox_solver, + foreign_call_executor, + ); + let main_witness = executor.execute_circuit(initial_witness)?; executor.witness_stack.push(0, main_witness); Ok(executor.finalize()) diff --git a/noir/noir-repo/tooling/nargo/src/ops/foreign_calls.rs b/noir/noir-repo/tooling/nargo/src/ops/foreign_calls.rs index bc91929e5e7..33767314a37 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/foreign_calls.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/foreign_calls.rs @@ -167,8 +167,15 @@ pub struct DefaultForeignCallExecutor { impl DefaultForeignCallExecutor { pub fn new(show_output: bool, resolver_url: Option<&str>) -> Self { let oracle_resolver = resolver_url.map(|resolver_url| { - let transport_builder = + let mut transport_builder = Builder::new().url(resolver_url).expect("Invalid oracle resolver URL"); + + 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::with_transport(transport_builder.build()) }); DefaultForeignCallExecutor { diff --git a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs index cfaaf27ea98..a62f4696328 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/optimize.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/optimize.rs @@ -1,25 +1,36 @@ +use acvm::acir::circuit::Program; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; - -/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for -/// multiple ACIR functions +use noirc_errors::debug_info::DebugInfo; pub fn optimize_program(mut compiled_program: CompiledProgram) -> CompiledProgram { - let (optimized_circuit, location_map) = - acvm::compiler::optimize(std::mem::take(&mut compiled_program.program.functions[0])); - compiled_program.program.functions[0] = optimized_circuit; - compiled_program.debug.update_acir(location_map); + compiled_program.program = + optimize_program_internal(compiled_program.program, &mut compiled_program.debug); compiled_program } pub fn optimize_contract(contract: CompiledContract) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { - let (optimized_bytecode, location_map) = - acvm::compiler::optimize(std::mem::take(&mut func.bytecode.functions[0])); - func.bytecode.functions[0] = optimized_bytecode; - func.debug.update_acir(location_map); + func.bytecode = optimize_program_internal(func.bytecode, &mut func.debug); func }); CompiledContract { functions, ..contract } } + +fn optimize_program_internal(mut program: Program, debug: &mut [DebugInfo]) -> Program { + let functions = std::mem::take(&mut program.functions); + + let optimized_functions = functions + .into_iter() + .enumerate() + .map(|(i, function)| { + let (optimized_circuit, location_map) = acvm::compiler::optimize(function); + debug[i].update_acir(location_map); + optimized_circuit + }) + .collect::>(); + + program.functions = optimized_functions; + program +} diff --git a/noir/noir-repo/tooling/nargo/src/ops/test.rs b/noir/noir-repo/tooling/nargo/src/ops/test.rs index 45b1a88f99c..b216fff827d 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/test.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/test.rs @@ -84,7 +84,7 @@ fn test_status_program_compile_fail(err: CompileError, test_function: &TestFunct /// passed/failed to determine the test status. fn test_status_program_compile_pass( test_function: &TestFunction, - debug: DebugInfo, + debug: Vec, circuit_execution: Result, ) -> TestStatus { let circuit_execution_err = match circuit_execution { diff --git a/noir/noir-repo/tooling/nargo/src/ops/transform.rs b/noir/noir-repo/tooling/nargo/src/ops/transform.rs index 274286a46e4..b4811bd5780 100644 --- a/noir/noir-repo/tooling/nargo/src/ops/transform.rs +++ b/noir/noir-repo/tooling/nargo/src/ops/transform.rs @@ -1,21 +1,17 @@ -use acvm::acir::circuit::ExpressionWidth; +use acvm::acir::circuit::{ExpressionWidth, Program}; use iter_extended::vecmap; use noirc_driver::{CompiledContract, CompiledProgram}; - -/// TODO(https://github.com/noir-lang/noir/issues/4428): Need to update how these passes are run to account for -/// multiple ACIR functions +use noirc_errors::debug_info::DebugInfo; pub fn transform_program( mut compiled_program: CompiledProgram, expression_width: ExpressionWidth, ) -> CompiledProgram { - let (optimized_circuit, location_map) = acvm::compiler::compile( - std::mem::take(&mut compiled_program.program.functions[0]), + compiled_program.program = transform_program_internal( + compiled_program.program, + &mut compiled_program.debug, expression_width, ); - - compiled_program.program.functions[0] = optimized_circuit; - compiled_program.debug.update_acir(location_map); compiled_program } @@ -24,14 +20,33 @@ pub fn transform_contract( expression_width: ExpressionWidth, ) -> CompiledContract { let functions = vecmap(contract.functions, |mut func| { - let (optimized_bytecode, location_map) = acvm::compiler::compile( - std::mem::take(&mut func.bytecode.functions[0]), - expression_width, - ); - func.bytecode.functions[0] = optimized_bytecode; - func.debug.update_acir(location_map); + func.bytecode = + transform_program_internal(func.bytecode, &mut func.debug, expression_width); + func }); CompiledContract { functions, ..contract } } + +fn transform_program_internal( + mut program: Program, + debug: &mut [DebugInfo], + expression_width: ExpressionWidth, +) -> Program { + let functions = std::mem::take(&mut program.functions); + + let optimized_functions = functions + .into_iter() + .enumerate() + .map(|(i, function)| { + let (optimized_circuit, location_map) = + acvm::compiler::compile(function, expression_width); + debug[i].update_acir(location_map); + optimized_circuit + }) + .collect::>(); + + program.functions = optimized_functions; + program +} diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs index 4f3e2886b2e..7cb5cd7846b 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/debug_cmd.rs @@ -232,7 +232,7 @@ pub(crate) fn debug_program( let initial_witness = compiled_program.abi.encode(inputs_map, None)?; let debug_artifact = DebugArtifact { - debug_symbols: vec![compiled_program.debug.clone()], + debug_symbols: compiled_program.debug.clone(), file_map: compiled_program.file_map.clone(), warnings: compiled_program.warnings.clone(), }; @@ -242,6 +242,7 @@ pub(crate) fn debug_program( &compiled_program.program.functions[0], debug_artifact, initial_witness, + &compiled_program.program.unconstrained_functions, ) .map_err(CliError::from) } diff --git a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs index 697f6d7c1ea..a353065491f 100644 --- a/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs +++ b/noir/noir-repo/tooling/nargo_cli/src/cli/execute_cmd.rs @@ -149,7 +149,7 @@ pub(crate) fn execute_program( Ok(solved_witness_stack) => Ok(solved_witness_stack), Err(err) => { let debug_artifact = DebugArtifact { - debug_symbols: vec![compiled_program.debug.clone()], + debug_symbols: compiled_program.debug.clone(), file_map: compiled_program.file_map.clone(), warnings: compiled_program.warnings.clone(), }; 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 e9609687ffb..67825362f92 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 @@ -97,17 +97,21 @@ pub(crate) fn run( if args.profile_info { for compiled_program in &compiled_programs { - let span_opcodes = compiled_program.debug.count_span_opcodes(); let debug_artifact = DebugArtifact::from(compiled_program.clone()); - print_span_opcodes(span_opcodes, &debug_artifact); + for function_debug in compiled_program.debug.iter() { + let span_opcodes = function_debug.count_span_opcodes(); + print_span_opcodes(span_opcodes, &debug_artifact); + } } for compiled_contract in &compiled_contracts { let debug_artifact = DebugArtifact::from(compiled_contract.clone()); let functions = &compiled_contract.functions; for contract_function in functions { - let span_opcodes = contract_function.debug.count_span_opcodes(); - print_span_opcodes(span_opcodes, &debug_artifact); + for function_debug in contract_function.debug.iter() { + let span_opcodes = function_debug.count_span_opcodes(); + print_span_opcodes(span_opcodes, &debug_artifact); + } } } } diff --git a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs index 922337cdb74..980d02ee5dc 100644 --- a/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs +++ b/noir/noir-repo/tooling/nargo_fmt/src/rewrite/typ.rs @@ -64,6 +64,7 @@ pub(crate) fn rewrite(visitor: &FmtVisitor, _shape: Shape, typ: UnresolvedType) | UnresolvedTypeData::Expression(_) | UnresolvedTypeData::String(_) | UnresolvedTypeData::FormatString(_, _) + | UnresolvedTypeData::Code | UnresolvedTypeData::TraitAsType(_, _) => visitor.slice(typ.span.unwrap()).into(), UnresolvedTypeData::Error => unreachable!(), } diff --git a/noir/noir-repo/tooling/noirc_abi/src/errors.rs b/noir/noir-repo/tooling/noirc_abi/src/errors.rs index 687fecfcc1d..4209a9e218b 100644 --- a/noir/noir-repo/tooling/noirc_abi/src/errors.rs +++ b/noir/noir-repo/tooling/noirc_abi/src/errors.rs @@ -1,4 +1,7 @@ -use crate::{input_parser::InputValue, AbiParameter, AbiType}; +use crate::{ + input_parser::{InputTypecheckingError, InputValue}, + AbiType, +}; use acvm::acir::native_types::Witness; use thiserror::Error; @@ -38,8 +41,8 @@ impl From for InputParserError { pub enum AbiError { #[error("Received parameters not expected by ABI: {0:?}")] UnexpectedParams(Vec), - #[error("The parameter {} is expected to be a {:?} but found incompatible value {value:?}", .param.name, .param.typ)] - TypeMismatch { param: AbiParameter, value: InputValue }, + #[error("The value passed for parameter `{}` does not match the specified type:\n{0}", .0.path())] + TypeMismatch(#[from] InputTypecheckingError), #[error("ABI expects the parameter `{0}`, but this was not found")] MissingParam(String), #[error( diff --git a/noir/noir-repo/tooling/noirc_abi/src/input_parser/mod.rs b/noir/noir-repo/tooling/noirc_abi/src/input_parser/mod.rs index f66e069d487..4cf66820b8d 100644 --- a/noir/noir-repo/tooling/noirc_abi/src/input_parser/mod.rs +++ b/noir/noir-repo/tooling/noirc_abi/src/input_parser/mod.rs @@ -1,6 +1,7 @@ use num_bigint::{BigInt, BigUint}; use num_traits::{Num, Zero}; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashSet}; +use thiserror::Error; use acvm::FieldElement; use serde::Serialize; @@ -22,63 +23,165 @@ pub enum InputValue { Struct(BTreeMap), } +#[derive(Debug, Error)] +pub enum InputTypecheckingError { + #[error("Value {value:?} does not fall within range of allowable values for a {typ:?}")] + OutsideOfValidRange { path: String, typ: AbiType, value: InputValue }, + #[error("Type {typ:?} is expected to have length {expected_length} but value {value:?} has length {actual_length}")] + LengthMismatch { + path: String, + typ: AbiType, + value: InputValue, + expected_length: usize, + actual_length: usize, + }, + #[error("Could not find value for required field `{expected_field}`. Found values for fields {found_fields:?}")] + MissingField { path: String, expected_field: String, found_fields: Vec }, + #[error("Additional unexpected field was provided for type {typ:?}. Found field named `{extra_field}`")] + UnexpectedField { path: String, typ: AbiType, extra_field: String }, + #[error("Type {typ:?} and value {value:?} do not match")] + IncompatibleTypes { path: String, typ: AbiType, value: InputValue }, +} + +impl InputTypecheckingError { + pub(crate) fn path(&self) -> &str { + match self { + InputTypecheckingError::OutsideOfValidRange { path, .. } + | InputTypecheckingError::LengthMismatch { path, .. } + | InputTypecheckingError::MissingField { path, .. } + | InputTypecheckingError::UnexpectedField { path, .. } + | InputTypecheckingError::IncompatibleTypes { path, .. } => path, + } + } +} + impl InputValue { /// Checks whether the ABI type matches the InputValue type - /// and also their arity - pub fn matches_abi(&self, abi_param: &AbiType) -> bool { + pub(crate) fn find_type_mismatch( + &self, + abi_param: &AbiType, + path: String, + ) -> Result<(), InputTypecheckingError> { match (self, abi_param) { - (InputValue::Field(_), AbiType::Field) => true, + (InputValue::Field(_), AbiType::Field) => Ok(()), (InputValue::Field(field_element), AbiType::Integer { width, .. }) => { - field_element.num_bits() <= *width + if field_element.num_bits() <= *width { + Ok(()) + } else { + Err(InputTypecheckingError::OutsideOfValidRange { + path, + typ: abi_param.clone(), + value: self.clone(), + }) + } } (InputValue::Field(field_element), AbiType::Boolean) => { - field_element.is_one() || field_element.is_zero() + if field_element.is_one() || field_element.is_zero() { + Ok(()) + } else { + Err(InputTypecheckingError::OutsideOfValidRange { + path, + typ: abi_param.clone(), + value: self.clone(), + }) + } } (InputValue::Vec(array_elements), AbiType::Array { length, typ, .. }) => { if array_elements.len() != *length as usize { - return false; + return Err(InputTypecheckingError::LengthMismatch { + path, + typ: abi_param.clone(), + value: self.clone(), + expected_length: *length as usize, + actual_length: array_elements.len(), + }); } // Check that all of the array's elements' values match the ABI as well. - array_elements.iter().all(|input_value| input_value.matches_abi(typ)) + for (i, element) in array_elements.iter().enumerate() { + let mut path = path.clone(); + path.push_str(&format!("[{i}]")); + + element.find_type_mismatch(typ, path)?; + } + Ok(()) } (InputValue::String(string), AbiType::String { length }) => { - string.len() == *length as usize + if string.len() == *length as usize { + Ok(()) + } else { + Err(InputTypecheckingError::LengthMismatch { + path, + typ: abi_param.clone(), + value: self.clone(), + actual_length: string.len(), + expected_length: *length as usize, + }) + } } (InputValue::Struct(map), AbiType::Struct { fields, .. }) => { - if map.len() != fields.len() { - return false; + for (field_name, field_type) in fields { + if let Some(value) = map.get(field_name) { + let mut path = path.clone(); + path.push_str(&format!(".{field_name}")); + value.find_type_mismatch(field_type, path)?; + } else { + return Err(InputTypecheckingError::MissingField { + path, + expected_field: field_name.to_string(), + found_fields: map.keys().cloned().collect(), + }); + } } - let field_types = BTreeMap::from_iter(fields.iter().cloned()); + if map.len() > fields.len() { + let expected_fields: HashSet = + fields.iter().map(|(field, _)| field.to_string()).collect(); + let extra_field = map.keys().find(|&key| !expected_fields.contains(key)).cloned().expect("`map` is larger than the expected type's `fields` so it must contain an unexpected field"); + return Err(InputTypecheckingError::UnexpectedField { + path, + typ: abi_param.clone(), + extra_field: extra_field.to_string(), + }); + } - // Check that all of the struct's fields' values match the ABI as well. - map.iter().all(|(field_name, field_value)| { - if let Some(field_type) = field_types.get(field_name) { - field_value.matches_abi(field_type) - } else { - false - } - }) + Ok(()) } (InputValue::Vec(vec_elements), AbiType::Tuple { fields }) => { if vec_elements.len() != fields.len() { - return false; + return Err(InputTypecheckingError::LengthMismatch { + path, + typ: abi_param.clone(), + value: self.clone(), + actual_length: vec_elements.len(), + expected_length: fields.len(), + }); } - - vec_elements - .iter() - .zip(fields) - .all(|(input_value, abi_param)| input_value.matches_abi(abi_param)) + // Check that all of the array's elements' values match the ABI as well. + for (i, (element, expected_typ)) in vec_elements.iter().zip(fields).enumerate() { + let mut path = path.clone(); + path.push_str(&format!(".{i}")); + element.find_type_mismatch(expected_typ, path)?; + } + Ok(()) } // All other InputValue-AbiType combinations are fundamentally incompatible. - _ => false, + _ => Err(InputTypecheckingError::IncompatibleTypes { + path, + typ: abi_param.clone(), + value: self.clone(), + }), } } + + /// Checks whether the ABI type matches the InputValue type. + pub fn matches_abi(&self, abi_param: &AbiType) -> bool { + self.find_type_mismatch(abi_param, String::new()).is_ok() + } } /// The different formats that are supported when parsing diff --git a/noir/noir-repo/tooling/noirc_abi/src/lib.rs b/noir/noir-repo/tooling/noirc_abi/src/lib.rs index 89a60b0ed26..6ad13500bdd 100644 --- a/noir/noir-repo/tooling/noirc_abi/src/lib.rs +++ b/noir/noir-repo/tooling/noirc_abi/src/lib.rs @@ -307,15 +307,7 @@ impl Abi { .ok_or_else(|| AbiError::MissingParam(param_name.clone()))? .clone(); - if !value.matches_abi(&expected_type) { - let param = self - .parameters - .iter() - .find(|param| param.name == param_name) - .unwrap() - .clone(); - return Err(AbiError::TypeMismatch { param, value }); - } + value.find_type_mismatch(&expected_type, param_name.clone())?; Self::encode_value(value, &expected_type).map(|v| (param_name, v)) }) diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/test/browser/errors.test.ts b/noir/noir-repo/tooling/noirc_abi_wasm/test/browser/errors.test.ts index 429a2d446a3..0f75ff64a3e 100644 --- a/noir/noir-repo/tooling/noirc_abi_wasm/test/browser/errors.test.ts +++ b/noir/noir-repo/tooling/noirc_abi_wasm/test/browser/errors.test.ts @@ -9,7 +9,7 @@ it('errors when an integer input overflows', async () => { const { abi, inputs } = await import('../shared/uint_overflow'); expect(() => abiEncode(abi, inputs)).to.throw( - 'The parameter foo is expected to be a Integer { sign: Unsigned, width: 32 } but found incompatible value Field(2³⁸)', + 'The value passed for parameter `foo` does not match the specified type:\nValue Field(2³⁸) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', ); }); diff --git a/noir/noir-repo/tooling/noirc_abi_wasm/test/node/errors.test.ts b/noir/noir-repo/tooling/noirc_abi_wasm/test/node/errors.test.ts index 0d007e64803..fba451b4a8c 100644 --- a/noir/noir-repo/tooling/noirc_abi_wasm/test/node/errors.test.ts +++ b/noir/noir-repo/tooling/noirc_abi_wasm/test/node/errors.test.ts @@ -5,7 +5,7 @@ it('errors when an integer input overflows', async () => { const { abi, inputs } = await import('../shared/uint_overflow'); expect(() => abiEncode(abi, inputs)).to.throw( - 'The parameter foo is expected to be a Integer { sign: Unsigned, width: 32 } but found incompatible value Field(2³⁸)', + 'The value passed for parameter `foo` does not match the specified type:\nValue Field(2³⁸) does not fall within range of allowable values for a Integer { sign: Unsigned, width: 32 }', ); }); diff --git a/scripts/earthly-ci b/scripts/earthly-ci new file mode 100755 index 00000000000..43eeb9b17aa --- /dev/null +++ b/scripts/earthly-ci @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# A wrapper for Earthly that is meant to caught signs of known intermittent failures and continue. +# The silver lining is if Earthly does crash, the cache can pick up the build. +set -eu -o pipefail + +# Flag to determine if -i is present +INTERACTIVE=false +# Check for -i flag in the arguments +for arg in "$@"; do + if [ "$arg" == "-i" ] || [ "$arg" == "--interactive" ]; then + INTERACTIVE=true + break + fi +done + +OUTPUT_FILE=$(mktemp) +# capture output to handle earthly edge cases +if $INTERACTIVE ; then + # don't play nice with tee if interactive + earthly $@ +elif ! earthly $@ 2>&1 | tee $OUTPUT_FILE >&2 ; then + # we try earthly once, capturing output + # if we get one of our (unfortunate) known failures, handle retries + # TODO potentially handle other intermittent errors here + if grep 'failed to get edge: inconsistent graph state' $OUTPUT_FILE >/dev/null ; then + # TODO when earthly is overloaded we sometimes get + # 'failed to solve: failed to get edge: inconsistent graph state' + echo "Got 'inconsistent graph state'. Restarting earthly. See https://github.com/earthly/earthly/issues/2454'" + earthly $@ + # TODO handle + # could not configure satellite: failed getting org: unable to authenticate: failed to execute login request: Post + else + # otherwise, propagate error + exit 1 + fi +fi diff --git a/scripts/earthly-cloud b/scripts/earthly-cloud deleted file mode 100755 index d2a0e39bc2c..00000000000 --- a/scripts/earthly-cloud +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env bash - -# This script uses Earthly cloud satellites based on a runner type and hash of the GITHUB_ACTOR environment variable. -# ARM or x86 can be specified. -# Usage: earthly-cloud [options] -# Arguments: -# runner type: The type of runner, e.g., 'build' or 'bench'. -# architecture: The target architecture, e.g., 'arm' or 'x86'. -set -eu -o pipefail - -# Check if at least two arguments are passed -if [ $# -lt 2 ]; then - echo "Error: Insufficient arguments provided." - echo "Usage: $0 [options]" - exit 1 -fi - -RUNNER_TYPE=$1 -ARCH=$2 -shift 2 - -if [ "$ARCH" == "arm" ]; then - PLATFORM=linux/arm64 -elif [ "$ARCH" == "x86" ]; then - PLATFORM=linux/amd64 -fi - -# default sizes for build type -if [ "$RUNNER_TYPE" == "build" ] ; then - SIZE=4xlarge - NUMBER_OF_RUNNERS=2 - if [ "$ARCH" = arm ] ; then - NUMBER_OF_RUNNERS=1 - fi - # TODO why cant we set this?? - # MAX_PARALLELISM=8 -elif [ "$RUNNER_TYPE" == "bench" ] ; then - SIZE=2xlarge - NUMBER_OF_RUNNERS=1 - # MAX_PARALLELISM=1 -elif [ "$RUNNER_TYPE" == "test" ] ; then - SIZE=4xlarge - NUMBER_OF_RUNNERS=1 -fi - -# Flag to determine if -i is present -INTERACTIVE=false -# Check for -i flag in the arguments -for arg in "$@"; do - if [ "$arg" == "-i" ] || [ "$arg" == "--interactive" ]; then - INTERACTIVE=true - break - fi -done - -# we hash our GITHUB_ACTOR to pick from 1 to NUMBER_RUNNERS (inclusive) as RUNNER_ID -# this means everyone gets assigned to runners based on their user group -NAME_HASH=$(cksum <<< "$GITHUB_ACTOR" | cut -f 1 -d ' ') -RUNNER_ID=$(($NAME_HASH % $NUMBER_OF_RUNNERS + 1)) -RUNNER=$RUNNER_TYPE-$RUNNER_ID-$ARCH -earthly sat --org aztec launch --size $SIZE --platform $PLATFORM $RUNNER || true -# --remote-cache=aztecprotocol/cache:bb-native-tests -EARTHLY_FLAGS="-P --no-output --org aztec --sat $RUNNER" -OUTPUT_FILE=$(mktemp) -# capture output to handle earthly edge cases -if $INTERACTIVE ; then - # don't play nice with tee if interactive - earthly $EARTHLY_FLAGS $@ -elif ! earthly $EARTHLY_FLAGS $@ 2>&1 | tee $OUTPUT_FILE >&2 ; then - # we try earthly once, capturing output - # if we get one of our (unfortunate) known failures, handle retries - # TODO potentially handle other intermittent errors here - if grep 'failed to get edge: inconsistent graph state' $OUTPUT_FILE >/dev/null ; then - # TODO when earthly is overloaded we sometimes get - # 'failed to solve: failed to get edge: inconsistent graph state' - echo "Got 'inconsistent graph state'. Restarting earthly. See https://github.com/earthly/earthly/issues/2454'" - earthly $EARTHLY_FLAGS $@ - # TODO handle - # could not configure satellite: failed getting org: unable to authenticate: failed to execute login request: Post - else - # otherwise, propagate error - exit 1 - fi -fi diff --git a/scripts/setup_env.sh b/scripts/setup_env.sh index 97fb8fd68a1..70ecf9d7654 100755 --- a/scripts/setup_env.sh +++ b/scripts/setup_env.sh @@ -8,6 +8,6 @@ echo FORCE_COLOR=1 >> $GITHUB_ENV echo "Logging in to Docker..." echo $1 | docker login -u aztecprotocolci --password-stdin -# Make earthly-cloud and earthly-cloud-bench scripts available +# Make earthly-ci script available echo "PATH=$(dirname $(realpath $0)):$PATH" >> $GITHUB_ENV echo "EARTHLY_CONFIG=$(git rev-parse --show-toplevel)/.github/earthly-ci-config.yml" >> $GITHUB_ENV \ No newline at end of file diff --git a/yarn-project/archiver/package.json b/yarn-project/archiver/package.json index 17e7cb0ffdf..e1de8022869 100644 --- a/yarn-project/archiver/package.json +++ b/yarn-project/archiver/package.json @@ -51,7 +51,6 @@ "@aztec/protocol-contracts": "workspace:^", "@aztec/types": "workspace:^", "debug": "^4.3.4", - "lmdb": "^2.9.2", "lodash.groupby": "^4.6.0", "lodash.omit": "^4.5.0", "tsc-watch": "^6.0.0", diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 6657106ef64..eb9a9661466 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -47,7 +47,7 @@ describe('Archiver', () => { let latestBlockNum = await archiver.getBlockNumber(); expect(latestBlockNum).toEqual(0); - const blocks = blockNumbers.map(x => L2Block.random(x, 4, x, x + 1, x * 2, x * 3)); + const blocks = blockNumbers.map(x => L2Block.random(x, 4, x, x + 1, 2, 2)); const publishTxs = blocks.map(block => block.body).map(makePublishTx); const rollupTxs = blocks.map(makeRollupTx); @@ -109,7 +109,7 @@ describe('Archiver', () => { expect(encryptedLogs.length).toEqual(blockNumbers.length); for (const [index, x] of blockNumbers.entries()) { - const expectedTotalNumEncryptedLogs = 4 * x * (x * 2); + const expectedTotalNumEncryptedLogs = 4 * x * 2; const totalNumEncryptedLogs = EncryptedL2BlockL2Logs.unrollLogs([encryptedLogs[index]]).length; expect(totalNumEncryptedLogs).toEqual(expectedTotalNumEncryptedLogs); } @@ -118,7 +118,7 @@ describe('Archiver', () => { expect(unencryptedLogs.length).toEqual(blockNumbers.length); blockNumbers.forEach((x, index) => { - const expectedTotalNumUnencryptedLogs = 4 * (x + 1) * (x * 3); + const expectedTotalNumUnencryptedLogs = 4 * (x + 1) * 2; const totalNumUnencryptedLogs = UnencryptedL2BlockL2Logs.unrollLogs([unencryptedLogs[index]]).length; expect(totalNumUnencryptedLogs).toEqual(expectedTotalNumUnencryptedLogs); }); @@ -141,7 +141,7 @@ describe('Archiver', () => { let latestBlockNum = await archiver.getBlockNumber(); expect(latestBlockNum).toEqual(0); - const blocks = blockNumbers.map(x => L2Block.random(x, 4, x, x + 1, x * 2, x * 3)); + const blocks = blockNumbers.map(x => L2Block.random(x, 4, x, x + 1, 2, 2)); const publishTxs = blocks.map(block => block.body).map(makePublishTx); const rollupTxs = blocks.map(makeRollupTx); diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index 4d0feafa58e..24ef0228b5d 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -300,7 +300,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch describe('getUnencryptedLogs', () => { const txsPerBlock = 4; const numPublicFunctionCalls = 3; - const numUnencryptedLogs = 4; + const numUnencryptedLogs = 2; const numBlocks = 10; let blocks: DataRetrieval; diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 7658dd95029..d0bfaa8ff32 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -671,7 +671,7 @@ export class AztecNodeService implements AztecNode { throw reverted[0].revertReason; } this.log.info(`Simulated tx ${tx.getTxHash()} succeeds`); - return returns; + return returns[0]; } public setConfig(config: Partial): Promise { diff --git a/yarn-project/aztec.js/src/contract/contract_function_interaction.ts b/yarn-project/aztec.js/src/contract/contract_function_interaction.ts index 5f8033124db..f0c2a9e3578 100644 --- a/yarn-project/aztec.js/src/contract/contract_function_interaction.ts +++ b/yarn-project/aztec.js/src/contract/contract_function_interaction.ts @@ -1,6 +1,6 @@ import { type FunctionCall, PackedValues, TxExecutionRequest } from '@aztec/circuit-types'; import { type AztecAddress, FunctionData, GasSettings, TxContext } from '@aztec/circuits.js'; -import { type FunctionAbi, FunctionType, encodeArguments } from '@aztec/foundation/abi'; +import { type FunctionAbi, FunctionType, decodeReturnValues, encodeArguments } from '@aztec/foundation/abi'; import { type Wallet } from '../account/wallet.js'; import { BaseContractInteraction, type SendMethodOptions } from './base_contract_interaction.js'; @@ -73,7 +73,6 @@ export class ContractFunctionInteraction extends BaseContractInteraction { * 2. It supports `unconstrained`, `private` and `public` functions * 3. For `private` execution it: * 3.a SKIPS the entrypoint and starts directly at the function - * 3.b SKIPS public execution entirely * 4. For `public` execution it: * 4.a Removes the `txRequest` value after ended simulation * 4.b Ignores the `from` in the options @@ -86,10 +85,6 @@ export class ContractFunctionInteraction extends BaseContractInteraction { return this.wallet.viewTx(this.functionDao.name, this.args, this.contractAddress, options.from); } - // TODO: If not unconstrained, we return a size 4 array of fields. - // TODO: It should instead return the correctly decoded value - // TODO: The return type here needs to be fixed! @LHerskind - if (this.functionDao.functionType == FunctionType.SECRET) { const nodeInfo = await this.wallet.getNodeInfo(); const packedArgs = PackedValues.fromValues(encodeArguments(this.functionDao, this.args)); @@ -103,13 +98,15 @@ export class ContractFunctionInteraction extends BaseContractInteraction { authWitnesses: [], gasSettings: options.gasSettings ?? GasSettings.simulation(), }); - const simulatedTx = await this.pxe.simulateTx(txRequest, false, options.from ?? this.wallet.getAddress()); - return simulatedTx.privateReturnValues?.[0]; + const simulatedTx = await this.pxe.simulateTx(txRequest, true, options.from ?? this.wallet.getAddress()); + const flattened = simulatedTx.privateReturnValues; + return flattened ? decodeReturnValues(this.functionDao, flattened) : []; } else { const txRequest = await this.create(); const simulatedTx = await this.pxe.simulateTx(txRequest, true); this.txRequest = undefined; - return simulatedTx.publicReturnValues?.[0]; + const flattened = simulatedTx.publicReturnValues; + return flattened ? decodeReturnValues(this.functionDao, flattened) : []; } } } diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 918630b042e..03e9ddbff8a 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -7,7 +7,6 @@ import { type PUBLIC_DATA_TREE_HEIGHT, } from '@aztec/circuits.js'; import { type L1ContractAddresses } from '@aztec/ethereum'; -import { type ProcessReturnValues } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { type Fr } from '@aztec/foundation/fields'; import { type ContractClassPublic, type ContractInstanceWithAddress } from '@aztec/types/contracts'; @@ -22,7 +21,7 @@ import { } from '../logs/index.js'; import { type MerkleTreeId } from '../merkle_tree_id.js'; import { type SiblingPath } from '../sibling_path/index.js'; -import { type Tx, type TxHash, type TxReceipt } from '../tx/index.js'; +import { type ProcessReturnValues, type Tx, type TxHash, type TxReceipt } from '../tx/index.js'; import { type TxEffect } from '../tx_effect.js'; import { type SequencerConfig } from './configs.js'; import { type L2BlockNumber } from './l2_block_number.js'; @@ -283,7 +282,7 @@ export interface AztecNode { * This currently just checks that the transaction execution succeeds. * @param tx - The transaction to simulate. **/ - simulatePublicCalls(tx: Tx): Promise; + simulatePublicCalls(tx: Tx): Promise; /** * Updates the configuration of this node. diff --git a/yarn-project/circuit-types/src/l2_block.test.ts b/yarn-project/circuit-types/src/l2_block.test.ts index 42283c1fe85..5a1a39c0699 100644 --- a/yarn-project/circuit-types/src/l2_block.test.ts +++ b/yarn-project/circuit-types/src/l2_block.test.ts @@ -16,7 +16,7 @@ describe('L2Block', () => { // The following 2 values are copied from `testComputeKernelLogsIterationWithoutLogs` in `Decoder.t.sol` const encodedLogs = Buffer.from('0000000400000000', 'hex'); const logs = EncryptedTxL2Logs.fromBuffer(encodedLogs, true); - const referenceLogsHash = Buffer.from('006003947a07e21c81ce2062539d6d6864fe999b58b03fc46f6c190d9eac9b39', 'hex'); + const referenceLogsHash = Buffer.alloc(32); const logsHash = logs.hash(); expect(logsHash).toEqual(referenceLogsHash); @@ -27,7 +27,7 @@ describe('L2Block', () => { // The following 2 values are copied from `testComputeKernelLogs1Iteration` in `Decoder.t.sol` const encodedLogs = Buffer.from('0000000c000000080000000493e78a70', 'hex'); const logs = EncryptedTxL2Logs.fromBuffer(encodedLogs, true); - const referenceLogsHash = Buffer.from('00f458589e520e9e9bdaf746a7d226c39124e4a438f21fd41e6117a90f25f9a6', 'hex'); + const referenceLogsHash = Buffer.from('0020f9217a7218a377a78d0e8929b87d31c32d270817fe8f5fe876c61b741024', 'hex'); const logsHash = logs.hash(); expect(logsHash).toEqual(referenceLogsHash); @@ -41,7 +41,7 @@ describe('L2Block', () => { 'hex', ); const logs = EncryptedTxL2Logs.fromBuffer(encodedLogs, true); - const referenceLogsHash = Buffer.from('0084c3495a8cc56372f8f1d1efc0512920dae0f134d679cf26a12aff1509de14', 'hex'); + const referenceLogsHash = Buffer.from('007e066525b587fdfb3704301ffcfa4b6a585d95491926d0fd5698f3ae603b18', 'hex'); const logsHash = logs.hash(); expect(logsHash).toEqual(referenceLogsHash); @@ -50,12 +50,13 @@ describe('L2Block', () => { // TS equivalent of `testComputeKernelLogsMiddleIterationWithoutLogs` in `Decoder.t.sol` it('correctly computes kernel logs hash when are logs from 3 iterations (2nd iter. without logs)', () => { // The following 2 values are copied from `testComputeKernelLogsMiddleIterationWithoutLogs` in `Decoder.t.sol` + // Note: as of resolving #5017, we skip zero len logs, so we expect this and the prev hash to be the same const encodedLogs = Buffer.from( '00000028000000080000000493e78a7000000000000000140000001006a86173c86c6d3f108eefc36e7fb014', 'hex', ); const logs = EncryptedTxL2Logs.fromBuffer(encodedLogs, true); - const referenceLogsHash = Buffer.from('00fb7a99b84aad205b5a8368c12a5a6b2dc19e5d623a601717b337cdadb56aa4', 'hex'); + const referenceLogsHash = Buffer.from('007e066525b587fdfb3704301ffcfa4b6a585d95491926d0fd5698f3ae603b18', 'hex'); const logsHash = logs.hash(); expect(logsHash).toEqual(referenceLogsHash); diff --git a/yarn-project/circuit-types/src/logs/encrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/encrypted_l2_log.ts index 4e11c696d2f..b181aa8e6d7 100644 --- a/yarn-project/circuit-types/src/logs/encrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/encrypted_l2_log.ts @@ -1,5 +1,5 @@ import { Fr, Point } from '@aztec/circuits.js'; -import { randomBytes } from '@aztec/foundation/crypto'; +import { randomBytes, sha256Trunc } from '@aztec/foundation/crypto'; /** * Represents an individual encrypted log entry. @@ -43,6 +43,15 @@ export class EncryptedL2Log { return new EncryptedL2Log(data); } + /** + * Calculates hash of serialized logs. + * @returns Buffer containing 248 bits of information of sha256 hash. + */ + public hash(): Buffer { + const preimage = this.toBuffer(); + return sha256Trunc(preimage); + } + /** * Crates a random log. * @returns A random log. diff --git a/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts index ae10dc63ed5..3b0af9d8bf7 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.test.ts @@ -5,7 +5,7 @@ function shouldBehaveLikeFunctionL2Logs( ) { describe(FunctionL2Logs.name, () => { it('can encode L2Logs to buffer and back', () => { - const l2Logs = FunctionL2Logs.random(42); + const l2Logs = FunctionL2Logs.random(3); const buffer = l2Logs.toBuffer(); const recovered = FunctionL2Logs.fromBuffer(buffer); @@ -14,7 +14,7 @@ function shouldBehaveLikeFunctionL2Logs( }); it('can encode L2Logs to JSON and back', () => { - const l2Logs = FunctionL2Logs.random(42); + const l2Logs = FunctionL2Logs.random(3); const buffer = l2Logs.toJSON(); const recovered = FunctionL2Logs.fromJSON(buffer); @@ -23,7 +23,7 @@ function shouldBehaveLikeFunctionL2Logs( }); it('getSerializedLength returns the correct length', () => { - const l2Logs = FunctionL2Logs.random(42); + const l2Logs = FunctionL2Logs.random(3); const buffer = l2Logs.toBuffer(); const recovered = FunctionL2Logs.fromBuffer(buffer); diff --git a/yarn-project/circuit-types/src/logs/function_l2_logs.ts b/yarn-project/circuit-types/src/logs/function_l2_logs.ts index 12c44942915..dd8650132d5 100644 --- a/yarn-project/circuit-types/src/logs/function_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/function_l2_logs.ts @@ -1,5 +1,6 @@ -import { sha256 } from '@aztec/foundation/crypto'; -import { BufferReader, prefixBufferWithLength, truncateAndPad } from '@aztec/foundation/serialize'; +import { MAX_ENCRYPTED_LOGS_PER_CALL, MAX_UNENCRYPTED_LOGS_PER_CALL } from '@aztec/circuits.js'; +import { sha256Trunc } from '@aztec/foundation/crypto'; +import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; import { EncryptedL2Log } from './encrypted_l2_log.js'; import { UnencryptedL2Log } from './unencrypted_l2_log.js'; @@ -38,12 +39,13 @@ export abstract class FunctionL2Logs l.hash())); + return sha256Trunc(preimage); } /** @@ -85,10 +87,12 @@ export class EncryptedFunctionL2Logs extends FunctionL2Logs { /** * Creates a new L2Logs object with `numLogs` logs. * @param numLogs - The number of logs to create. - * @param logType - The type of logs to generate. * @returns A new EncryptedFunctionL2Logs object. */ public static random(numLogs: number): EncryptedFunctionL2Logs { + if (numLogs > MAX_ENCRYPTED_LOGS_PER_CALL) { + throw new Error(`Trying to create ${numLogs} logs for one call (max: ${MAX_ENCRYPTED_LOGS_PER_CALL})`); + } const logs: EncryptedL2Log[] = []; for (let i = 0; i < numLogs; i++) { logs.push(EncryptedL2Log.random()); @@ -135,10 +139,12 @@ export class UnencryptedFunctionL2Logs extends FunctionL2Logs /** * Creates a new L2Logs object with `numLogs` logs. * @param numLogs - The number of logs to create. - * @param logType - The type of logs to generate. * @returns A new UnencryptedFunctionL2Logs object. */ public static random(numLogs: number): UnencryptedFunctionL2Logs { + if (numLogs > MAX_UNENCRYPTED_LOGS_PER_CALL) { + throw new Error(`Trying to create ${numLogs} logs for one call (max: ${MAX_UNENCRYPTED_LOGS_PER_CALL})`); + } const logs: UnencryptedL2Log[] = []; for (let i = 0; i < numLogs; i++) { logs.push(UnencryptedL2Log.random()); diff --git a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts index 843de795196..6b0227c4334 100644 --- a/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/l2_block_l2_logs.test.ts @@ -3,7 +3,7 @@ import { EncryptedL2BlockL2Logs, UnencryptedL2BlockL2Logs } from './l2_block_l2_ function shouldBehaveLikeL2BlockL2Logs(L2BlockL2Logs: typeof EncryptedL2BlockL2Logs | typeof UnencryptedL2BlockL2Logs) { describe(L2BlockL2Logs.name, () => { it('can encode L2Logs to buffer and back', () => { - const l2Logs = L2BlockL2Logs.random(3, 6, 2); + const l2Logs = L2BlockL2Logs.random(3, 4, 2); const buffer = l2Logs.toBuffer(); const recovered = L2BlockL2Logs.fromBuffer(buffer); @@ -12,7 +12,7 @@ function shouldBehaveLikeL2BlockL2Logs(L2BlockL2Logs: typeof EncryptedL2BlockL2L }); it('getSerializedLength returns the correct length', () => { - const l2Logs = L2BlockL2Logs.random(3, 6, 2); + const l2Logs = L2BlockL2Logs.random(3, 4, 2); const buffer = l2Logs.toBuffer(); const recovered = L2BlockL2Logs.fromBuffer(buffer); @@ -21,7 +21,7 @@ function shouldBehaveLikeL2BlockL2Logs(L2BlockL2Logs: typeof EncryptedL2BlockL2L }); it('serializes to and from JSON', () => { - const l2Logs = L2BlockL2Logs.random(3, 6, 2); + const l2Logs = L2BlockL2Logs.random(3, 4, 2); const json = l2Logs.toJSON(); const recovered = L2BlockL2Logs.fromJSON(json); expect(recovered).toEqual(l2Logs); diff --git a/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts b/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts index 6f706a4c72b..6be5194aa49 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.test.ts @@ -3,7 +3,7 @@ import { EncryptedTxL2Logs, UnencryptedTxL2Logs } from './tx_l2_logs.js'; function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof EncryptedTxL2Logs | typeof UnencryptedTxL2Logs) { describe(TxL2Logs.name, () => { it('can encode TxL2Logs to buffer and back', () => { - const l2Logs = TxL2Logs.random(6, 2); + const l2Logs = TxL2Logs.random(4, 2); const buffer = l2Logs.toBuffer(); const recovered = TxL2Logs.fromBuffer(buffer); @@ -12,7 +12,7 @@ function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof EncryptedTxL2Logs | typeof Un }); it('can encode TxL2Logs to JSON and back', () => { - const l2Logs = TxL2Logs.random(6, 2); + const l2Logs = TxL2Logs.random(4, 2); const buffer = l2Logs.toJSON(); const recovered = TxL2Logs.fromJSON(buffer); @@ -21,7 +21,7 @@ function shouldBehaveLikeTxL2Logs(TxL2Logs: typeof EncryptedTxL2Logs | typeof Un }); it('getSerializedLength returns the correct length', () => { - const l2Logs = TxL2Logs.random(6, 2); + const l2Logs = TxL2Logs.random(4, 2); const buffer = l2Logs.toBuffer(); const recovered = TxL2Logs.fromBuffer(buffer); diff --git a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts index bd6fe976ed0..e0814eafa4e 100644 --- a/yarn-project/circuit-types/src/logs/tx_l2_logs.ts +++ b/yarn-project/circuit-types/src/logs/tx_l2_logs.ts @@ -1,5 +1,6 @@ -import { sha256 } from '@aztec/foundation/crypto'; -import { BufferReader, prefixBufferWithLength, truncateAndPad } from '@aztec/foundation/serialize'; +import { MAX_ENCRYPTED_LOGS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX } from '@aztec/circuits.js'; +import { sha256Trunc } from '@aztec/foundation/crypto'; +import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; import isEqual from 'lodash.isequal'; @@ -86,12 +87,12 @@ export abstract class TxL2Logs { const logsHashes: [Buffer, Buffer] = [Buffer.alloc(32), Buffer.alloc(32)]; let kernelPublicInputsLogsHash = Buffer.alloc(32); - for (const logsFromSingleFunctionCall of this.functionLogs) { + for (const logsFromSingleFunctionCall of this.unrollLogs()) { logsHashes[0] = kernelPublicInputsLogsHash; logsHashes[1] = logsFromSingleFunctionCall.hash(); // privateCircuitPublicInputsLogsHash // Hash logs hash from the public inputs of previous kernel iteration and logs hash from private circuit public inputs - kernelPublicInputsLogsHash = truncateAndPad(sha256(Buffer.concat(logsHashes))); + kernelPublicInputsLogsHash = sha256Trunc(Buffer.concat(logsHashes)); } return kernelPublicInputsLogsHash; @@ -129,6 +130,11 @@ export class UnencryptedTxL2Logs extends TxL2Logs { * @returns A new `TxL2Logs` object. */ public static random(numCalls: number, numLogsPerCall: number): UnencryptedTxL2Logs { + if (numCalls * numLogsPerCall > MAX_UNENCRYPTED_LOGS_PER_TX) { + throw new Error( + `Trying to create ${numCalls * numLogsPerCall} logs for one tx (max: ${MAX_UNENCRYPTED_LOGS_PER_TX})`, + ); + } const functionLogs: UnencryptedFunctionL2Logs[] = []; for (let i = 0; i < numCalls; i++) { functionLogs.push(UnencryptedFunctionL2Logs.random(numLogsPerCall)); @@ -178,6 +184,11 @@ export class EncryptedTxL2Logs extends TxL2Logs { * @returns A new `TxL2Logs` object. */ public static random(numCalls: number, numLogsPerCall: number): EncryptedTxL2Logs { + if (numCalls * numLogsPerCall > MAX_ENCRYPTED_LOGS_PER_TX) { + throw new Error( + `Trying to create ${numCalls * numLogsPerCall} logs for one tx (max: ${MAX_ENCRYPTED_LOGS_PER_TX})`, + ); + } const functionLogs: EncryptedFunctionL2Logs[] = []; for (let i = 0; i < numCalls; i++) { functionLogs.push(EncryptedFunctionL2Logs.random(numLogsPerCall)); diff --git a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts index a8bc9ee0fec..40d7e598cf5 100644 --- a/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts +++ b/yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts @@ -1,6 +1,6 @@ import { AztecAddress } from '@aztec/circuits.js'; import { EventSelector } from '@aztec/foundation/abi'; -import { randomBytes } from '@aztec/foundation/crypto'; +import { randomBytes, sha256Trunc } from '@aztec/foundation/crypto'; import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; /** @@ -82,6 +82,15 @@ export class UnencryptedL2Log { return new UnencryptedL2Log(contractAddress, selector, data); } + /** + * Calculates hash of serialized logs. + * @returns Buffer containing 248 bits of information of sha256 hash. + */ + public hash(): Buffer { + const preimage = this.toBuffer(); + return sha256Trunc(preimage); + } + /** * Crates a random log. * @returns A random log. diff --git a/yarn-project/circuit-types/src/mocks.ts b/yarn-project/circuit-types/src/mocks.ts index f0b3c805ad9..3c613163756 100644 --- a/yarn-project/circuit-types/src/mocks.ts +++ b/yarn-project/circuit-types/src/mocks.ts @@ -6,12 +6,14 @@ import { PartialPrivateTailPublicInputsForPublic, PrivateKernelTailCircuitPublicInputs, Proof, + type PublicCallRequest, + SideEffect, SideEffectLinkedToNoteHash, computeContractClassId, getContractClassFromArtifact, } from '@aztec/circuits.js'; import { makePublicCallRequest } from '@aztec/circuits.js/testing'; -import { type ContractArtifact, type DecodedReturn } from '@aztec/foundation/abi'; +import { type ContractArtifact } from '@aztec/foundation/abi'; import { makeTuple } from '@aztec/foundation/array'; import { times } from '@aztec/foundation/collection'; import { randomBytes } from '@aztec/foundation/crypto'; @@ -21,7 +23,7 @@ import { type ContractInstanceWithAddress, SerializableContractInstance } from ' import { EncryptedL2Log } from './logs/encrypted_l2_log.js'; import { EncryptedFunctionL2Logs, EncryptedTxL2Logs, Note, UnencryptedTxL2Logs } from './logs/index.js'; import { ExtendedNote } from './notes/index.js'; -import { SimulatedTx, Tx, TxHash } from './tx/index.js'; +import { type ProcessReturnValues, SimulatedTx, Tx, TxHash } from './tx/index.js'; /** * Testing utility to create empty logs composed from a single empty log. @@ -39,18 +41,27 @@ export const mockTx = ( hasLogs = false, numberOfNonRevertiblePublicCallRequests = MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX / 2, numberOfRevertiblePublicCallRequests = MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX / 2, + publicCallRequests = [], }: { hasLogs?: boolean; numberOfNonRevertiblePublicCallRequests?: number; numberOfRevertiblePublicCallRequests?: number; + publicCallRequests?: PublicCallRequest[]; } = {}, ) => { - const totalPublicCallRequests = numberOfNonRevertiblePublicCallRequests + numberOfRevertiblePublicCallRequests; - const publicCallRequests = times(totalPublicCallRequests, i => makePublicCallRequest(seed + 0x100 + i)); + const totalPublicCallRequests = + numberOfNonRevertiblePublicCallRequests + numberOfRevertiblePublicCallRequests || publicCallRequests.length; + if (publicCallRequests.length && publicCallRequests.length !== totalPublicCallRequests) { + throw new Error( + `Provided publicCallRequests does not match the required number of call requests. Expected ${totalPublicCallRequests}. Got ${publicCallRequests.length}`, + ); + } const isForPublic = totalPublicCallRequests > 0; const data = PrivateKernelTailCircuitPublicInputs.empty(); const firstNullifier = new SideEffectLinkedToNoteHash(new Fr(seed + 1), new Fr(seed + 2), Fr.ZERO); + const encryptedLogs = hasLogs ? EncryptedTxL2Logs.random(2, 3) : EncryptedTxL2Logs.empty(); // 2 priv function invocations creating 3 encrypted logs each + const unencryptedLogs = hasLogs ? UnencryptedTxL2Logs.random(2, 1) : UnencryptedTxL2Logs.empty(); // 2 priv function invocations creating 1 unencrypted log each data.constants.gasSettings = GasSettings.default(); if (isForPublic) { @@ -59,29 +70,37 @@ export const mockTx = ( data.forPublic.endNonRevertibleData.newNullifiers[0] = firstNullifier; - data.forPublic.end.publicCallStack = makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, i => - i < numberOfRevertiblePublicCallRequests ? publicCallRequests[i].toCallRequest() : CallRequest.empty(), - ); + publicCallRequests = publicCallRequests.length + ? publicCallRequests.slice().sort((a, b) => b.callContext.sideEffectCounter - a.callContext.sideEffectCounter) + : times(totalPublicCallRequests, i => makePublicCallRequest(seed + 0x100 + i)); data.forPublic.endNonRevertibleData.publicCallStack = makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, i => i < numberOfNonRevertiblePublicCallRequests - ? publicCallRequests[i + numberOfRevertiblePublicCallRequests].toCallRequest() + ? publicCallRequests[numberOfRevertiblePublicCallRequests + i].toCallRequest() : CallRequest.empty(), ); - } else { - data.forRollup!.end.newNullifiers[0] = firstNullifier.value; - } - - const target = isForPublic ? data.forPublic! : data.forRollup!; + if (hasLogs) { + let i = 1; // 0 used in first nullifier + encryptedLogs.functionLogs.forEach((log, j) => { + // ts complains if we dont check .forPublic here, even though it is defined ^ + if (data.forPublic) { + data.forPublic.end.encryptedLogsHashes[j] = new SideEffect(Fr.fromBuffer(log.hash()), new Fr(i++)); + } + }); + unencryptedLogs.functionLogs.forEach((log, j) => { + if (data.forPublic) { + data.forPublic.end.unencryptedLogsHashes[j] = new SideEffect(Fr.fromBuffer(log.hash()), new Fr(i++)); + } + }); + } - const encryptedLogs = hasLogs ? EncryptedTxL2Logs.random(8, 3) : EncryptedTxL2Logs.empty(); // 8 priv function invocations creating 3 encrypted logs each - const unencryptedLogs = hasLogs ? UnencryptedTxL2Logs.random(11, 2) : UnencryptedTxL2Logs.empty(); // 8 priv function invocations creating 3 encrypted logs each - if (!hasLogs) { - target.end.encryptedLogsHash = Fr.ZERO; - target.end.unencryptedLogsHash = Fr.ZERO; + data.forPublic.end.publicCallStack = makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, i => + i < numberOfRevertiblePublicCallRequests ? publicCallRequests[i].toCallRequest() : CallRequest.empty(), + ); } else { - target.end.encryptedLogsHash = Fr.fromBuffer(encryptedLogs.hash()); - target.end.unencryptedLogsHash = Fr.fromBuffer(unencryptedLogs.hash()); + data.forRollup!.end.newNullifiers[0] = firstNullifier.value; + data.forRollup!.end.encryptedLogsHash = hasLogs ? Fr.fromBuffer(encryptedLogs.hash()) : Fr.ZERO; + data.forRollup!.end.unencryptedLogsHash = hasLogs ? Fr.fromBuffer(unencryptedLogs.hash()) : Fr.ZERO; } const tx = new Tx(data, new Proof(Buffer.alloc(0)), encryptedLogs, unencryptedLogs, publicCallRequests); @@ -94,7 +113,7 @@ export const mockTxForRollup = (seed = 1, { hasLogs = false }: { hasLogs?: boole export const mockSimulatedTx = (seed = 1, hasLogs = true) => { const tx = mockTx(seed, { hasLogs }); - const dec: DecodedReturn = [1n, 2n, 3n, 4n]; + const dec: ProcessReturnValues = [new Fr(1n), new Fr(2n), new Fr(3n), new Fr(4n)]; return new SimulatedTx(tx, dec, dec); }; diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.test.ts b/yarn-project/circuit-types/src/tx/simulated_tx.test.ts index 29cc0019477..167c91259fa 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.test.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.test.ts @@ -6,4 +6,11 @@ describe('simulated_tx', () => { const simulatedTx = mockSimulatedTx(); expect(SimulatedTx.fromJSON(simulatedTx.toJSON())).toEqual(simulatedTx); }); + + it('convert undefined effects to and from json', () => { + const simulatedTx = mockSimulatedTx(); + simulatedTx.privateReturnValues = undefined; + simulatedTx.publicReturnValues = undefined; + expect(SimulatedTx.fromJSON(simulatedTx.toJSON())).toEqual(simulatedTx); + }); }); diff --git a/yarn-project/circuit-types/src/tx/simulated_tx.ts b/yarn-project/circuit-types/src/tx/simulated_tx.ts index febf33cdfb4..baef7a2d4ea 100644 --- a/yarn-project/circuit-types/src/tx/simulated_tx.ts +++ b/yarn-project/circuit-types/src/tx/simulated_tx.ts @@ -1,8 +1,9 @@ -import { AztecAddress } from '@aztec/circuits.js'; -import { type ProcessReturnValues } from '@aztec/foundation/abi'; +import { Fr } from '@aztec/circuits.js'; import { Tx } from './tx.js'; +export type ProcessReturnValues = Fr[] | undefined; + export class SimulatedTx { constructor( public tx: Tx, @@ -15,17 +16,11 @@ export class SimulatedTx { * @returns A plain object with SimulatedTx properties. */ public toJSON() { - const returnToJson = (data: ProcessReturnValues): string => { - const replacer = (key: string, value: any): any => { - if (typeof value === 'bigint') { - return value.toString() + 'n'; // Indicate bigint with "n" - } else if (value instanceof AztecAddress) { - return value.toString(); - } else { - return value; - } - }; - return JSON.stringify(data, replacer); + const returnToJson = (data: ProcessReturnValues | undefined): string => { + if (data === undefined) { + return JSON.stringify(data); + } + return JSON.stringify(data.map(fr => fr.toString())); }; return { @@ -41,22 +36,11 @@ export class SimulatedTx { * @returns A Tx class object. */ public static fromJSON(obj: any) { - const returnFromJson = (json: string): ProcessReturnValues => { - if (json == undefined) { + const returnFromJson = (json: string): ProcessReturnValues | undefined => { + if (json === undefined) { return json; } - const reviver = (key: string, value: any): any => { - if (typeof value === 'string') { - if (value.match(/\d+n$/)) { - // Detect bigint serialization - return BigInt(value.slice(0, -1)); - } else if (value.match(/^0x[a-fA-F0-9]{64}$/)) { - return AztecAddress.fromString(value); - } - } - return value; - }; - return JSON.parse(json, reviver); + return JSON.parse(json).map(Fr.fromString); }; const tx = Tx.fromJSON(obj.tx); diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index 02d4273ab6a..1bf14f809be 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -40,6 +40,8 @@ export class Tx { public readonly enqueuedPublicFunctionCalls: PublicCallRequest[], ) { if (this.unencryptedLogs.functionLogs.length < this.encryptedLogs.functionLogs.length) { + // TODO(Miranda): This error was not throwing in some cases, as logs are nested objects which would show len 1 even if no logs existed + // Many tests produce enc logs and no unenc logs, so this error should have been throwing even in good cases // This check is present because each private function invocation creates encrypted FunctionL2Logs object and // both public and private function invocations create unencrypted FunctionL2Logs object. Hence "num unencrypted" // >= "num encrypted". diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index abea48aef02..9ac707568fd 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -12,6 +12,8 @@ export const MAX_NOTE_HASH_READ_REQUESTS_PER_CALL = 32; export const MAX_NULLIFIER_READ_REQUESTS_PER_CALL = 2; export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL = 2; export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_CALL = 1; +export const MAX_ENCRYPTED_LOGS_PER_CALL = 4; +export const MAX_UNENCRYPTED_LOGS_PER_CALL = 4; export const MAX_NEW_NOTE_HASHES_PER_TX = 64; export const MAX_NEW_NULLIFIERS_PER_TX = 64; export const MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX = 8; @@ -23,8 +25,11 @@ export const MAX_NOTE_HASH_READ_REQUESTS_PER_TX = 128; export const MAX_NULLIFIER_READ_REQUESTS_PER_TX = 8; export const MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX = 8; export const MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX = 4; +export const MAX_ENCRYPTED_LOGS_PER_TX = 8; +export const MAX_UNENCRYPTED_LOGS_PER_TX = 8; export const NUM_ENCRYPTED_LOGS_HASHES_PER_TX = 1; export const NUM_UNENCRYPTED_LOGS_HASHES_PER_TX = 1; +export const MAX_PUBLIC_DATA_HINTS = 64; export const NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP = 16; export const VK_TREE_HEIGHT = 3; export const FUNCTION_TREE_HEIGHT = 5; @@ -55,7 +60,7 @@ export const INITIALIZATION_SLOT_SEPARATOR = 1000_000_000; export const INITIAL_L2_BLOCK_NUM = 1; export const BLOB_SIZE_IN_BYTES = 126976; export const NESTED_CALL_L2_GAS_BUFFER = 20000; -export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 16000; +export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 16200; export const MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 3000; export const MAX_PACKED_BYTECODE_SIZE_PER_UNCONSTRAINED_FUNCTION_IN_FIELDS = 3000; export const REGISTERER_PRIVATE_FUNCTION_BROADCASTED_ADDITIONAL_FIELDS = 19; @@ -68,7 +73,7 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99n; export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n; -export const DEPLOYER_CONTRACT_ADDRESS = 0x1d2c645a18ab4d81672dd779bf1ea4fa2c0b4a2f09bf59d3fb4ee408299d00b2n; +export const DEPLOYER_CONTRACT_ADDRESS = 0x1b5ecf3d26907648cf737f4304759b8c5850478e839e72f8ce1f5791b286e8f2n; export const L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 17; export const MAX_NOTE_FIELDS_LENGTH = 20; export const GET_NOTE_ORACLE_RETURN_LENGTH = 23; @@ -95,9 +100,9 @@ export const MAX_BLOCK_NUMBER_LENGTH = 2; export const NULLIFIER_KEY_VALIDATION_REQUEST_LENGTH = 4; export const NULLIFIER_KEY_VALIDATION_REQUEST_CONTEXT_LENGTH = 5; export const PARTIAL_STATE_REFERENCE_LENGTH = 6; -export const PRIVATE_CALL_STACK_ITEM_LENGTH = 224; -export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 221; -export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 215; +export const PRIVATE_CALL_STACK_ITEM_LENGTH = 238; +export const PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH = 235; +export const PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH = 222; export const STATE_REFERENCE_LENGTH = 8; export const TX_CONTEXT_DATA_LENGTH = 4; export const TX_REQUEST_LENGTH = 18; diff --git a/yarn-project/circuits.js/src/hints/build_hints.test.ts b/yarn-project/circuits.js/src/hints/build_hints.test.ts index 7ac9ee39a52..5df210ca1e8 100644 --- a/yarn-project/circuits.js/src/hints/build_hints.test.ts +++ b/yarn-project/circuits.js/src/hints/build_hints.test.ts @@ -22,10 +22,8 @@ import { buildNullifierNonExistentReadRequestHints, buildNullifierReadRequestHin describe('buildNullifierReadRequestHints', () => { const contractAddress = AztecAddress.random(); const settledNullifierInnerValue = 99999; - const settledNullifierValue = makeNullifier(settledNullifierInnerValue).value; const oracle = { - getNullifierMembershipWitness: (value: Fr) => - value.equals(settledNullifierValue) ? ({ membershipWitness: {}, leafPreimage: {} } as any) : undefined, + getNullifierMembershipWitness: () => ({ membershipWitness: {}, leafPreimage: {} } as any), }; let nullifierReadRequests: Tuple; let nullifiers: Tuple; @@ -113,11 +111,6 @@ describe('buildNullifierReadRequestHints', () => { const hints = await buildHints(); expect(hints).toEqual(expectedHints); }); - - it('throws if reading an unknown nullifier', async () => { - nullifierReadRequests[0] = makeReadRequest(88888); - await expect(buildHints()).rejects.toThrow('Read request is reading an unknown nullifier value.'); - }); }); describe('buildNullifierNonExistentReadRequestHints', () => { diff --git a/yarn-project/circuits.js/src/hints/build_hints.ts b/yarn-project/circuits.js/src/hints/build_hints.ts index 1266082c2d0..302ed3a14f9 100644 --- a/yarn-project/circuits.js/src/hints/build_hints.ts +++ b/yarn-project/circuits.js/src/hints/build_hints.ts @@ -17,14 +17,14 @@ import { NullifierReadRequestHintsBuilder } from '../structs/read_request_hints. import { SideEffectLinkedToNoteHash } from '../structs/side_effects.js'; import { countAccumulatedItems } from '../utils/index.js'; -export interface NullifierMembershipWitnessWithPreimage { +interface NullifierMembershipWitnessWithPreimage { membershipWitness: MembershipWitness; leafPreimage: IndexedTreeLeafPreimage; } export async function buildNullifierReadRequestHints( oracle: { - getNullifierMembershipWitness(nullifier: Fr): Promise; + getNullifierMembershipWitness(nullifier: Fr): Promise; }, nullifierReadRequests: Tuple, nullifiers: Tuple, @@ -46,10 +46,6 @@ export async function buildNullifierReadRequestHints( builder.addPendingReadRequest(i, pendingValueIndex); } else { const membershipWitnessWithPreimage = await oracle.getNullifierMembershipWitness(value); - if (!membershipWitnessWithPreimage) { - throw new Error('Read request is reading an unknown nullifier value.'); - } - builder.addSettledReadRequest( i, membershipWitnessWithPreimage.membershipWitness, diff --git a/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts b/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts new file mode 100644 index 00000000000..a041d8fd32f --- /dev/null +++ b/yarn-project/circuits.js/src/hints/build_public_data_hints.test.ts @@ -0,0 +1,123 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { Fr } from '@aztec/foundation/fields'; +import { type Tuple } from '@aztec/foundation/serialize'; + +import { + MAX_PUBLIC_DATA_HINTS, + MAX_PUBLIC_DATA_READS_PER_TX, + type MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, +} from '../constants.gen.js'; +import { PublicDataRead, PublicDataTreeLeafPreimage, PublicDataUpdateRequest } from '../structs/index.js'; +import { buildPublicDataHints } from './build_public_data_hints.js'; + +class ExpectedHint { + constructor(public leafSlot: number, public value: number, public matchOrLowLeafSlot: number) {} + + static empty() { + return new ExpectedHint(0, 0, 0); + } + + toExpectedObject() { + return expect.objectContaining({ + leafSlot: new Fr(this.leafSlot), + value: new Fr(this.value), + leafPreimage: expect.objectContaining({ slot: new Fr(this.matchOrLowLeafSlot) }), + }); + } +} + +describe('buildPublicDataHints', () => { + let publicDataReads: Tuple; + let publicDataUpdateRequests: Tuple; + let expectedHints: Tuple; + + const publicDataLeaves = [ + new PublicDataTreeLeafPreimage(new Fr(22), new Fr(200), new Fr(33), 0n), + new PublicDataTreeLeafPreimage(new Fr(11), new Fr(100), new Fr(22), 0n), + new PublicDataTreeLeafPreimage(new Fr(0), new Fr(0), new Fr(11), 0n), + ]; + + const makePublicDataRead = (leafSlot: number, value: number) => new PublicDataRead(new Fr(leafSlot), new Fr(value)); + const makePublicDataWrite = (leafSlot: number, value: number) => + new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value)); + + const oracle = { + getMatchOrLowPublicDataMembershipWitness: (leafSlot: bigint) => { + const leafPreimage = publicDataLeaves.find(l => l.slot.toBigInt() <= leafSlot); + return { membershipWitness: {}, leafPreimage } as any; + }, + }; + + const buildHints = () => buildPublicDataHints(oracle, publicDataReads, publicDataUpdateRequests); + + const buildAndCheckHints = async () => { + const hints = await buildHints(); + const partialHints = expectedHints.map(h => h.toExpectedObject()); + expect(hints).toEqual(partialHints); + }; + + beforeEach(() => { + publicDataReads = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty); + publicDataUpdateRequests = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataUpdateRequest.empty); + expectedHints = makeTuple(MAX_PUBLIC_DATA_HINTS, ExpectedHint.empty); + }); + + it('returns empty hints', async () => { + await buildAndCheckHints(); + }); + + it('builds hints for reads for uninitialized slots', async () => { + publicDataReads[0] = makePublicDataRead(12, 0); + publicDataReads[1] = makePublicDataRead(39, 0); + expectedHints[0] = new ExpectedHint(12, 0, 11); + expectedHints[1] = new ExpectedHint(39, 0, 22); + + await buildAndCheckHints(); + }); + + it('builds hints for reads for initialized slots', async () => { + publicDataReads[0] = makePublicDataRead(22, 200); + publicDataReads[1] = makePublicDataRead(11, 100); + expectedHints[0] = new ExpectedHint(22, 200, 22); + expectedHints[1] = new ExpectedHint(11, 100, 11); + + await buildAndCheckHints(); + }); + + it('builds hints for writes to uninitialized slots', async () => { + publicDataUpdateRequests[0] = makePublicDataWrite(5, 500); + publicDataUpdateRequests[1] = makePublicDataWrite(17, 700); + expectedHints[0] = new ExpectedHint(5, 0, 0); + expectedHints[1] = new ExpectedHint(17, 0, 11); + + await buildAndCheckHints(); + }); + + it('builds hints for writes to initialized slots', async () => { + publicDataUpdateRequests[0] = makePublicDataWrite(11, 111); + publicDataUpdateRequests[1] = makePublicDataWrite(22, 222); + expectedHints[0] = new ExpectedHint(11, 100, 11); + expectedHints[1] = new ExpectedHint(22, 200, 22); + + await buildAndCheckHints(); + }); + + it('builds hints for mixed reads and writes', async () => { + publicDataReads[0] = makePublicDataRead(22, 200); + publicDataReads[1] = makePublicDataRead(12, 0); + publicDataReads[2] = makePublicDataRead(39, 0); + publicDataReads[3] = makePublicDataRead(11, 100); + publicDataUpdateRequests[0] = makePublicDataWrite(11, 111); + publicDataUpdateRequests[1] = makePublicDataWrite(5, 500); + publicDataUpdateRequests[2] = makePublicDataWrite(17, 700); + publicDataUpdateRequests[3] = makePublicDataWrite(22, 222); + expectedHints[0] = new ExpectedHint(22, 200, 22); + expectedHints[1] = new ExpectedHint(12, 0, 11); + expectedHints[2] = new ExpectedHint(39, 0, 22); + expectedHints[3] = new ExpectedHint(11, 100, 11); + expectedHints[4] = new ExpectedHint(5, 0, 0); + expectedHints[5] = new ExpectedHint(17, 0, 11); + + await buildAndCheckHints(); + }); +}); diff --git a/yarn-project/circuits.js/src/hints/build_public_data_hints.ts b/yarn-project/circuits.js/src/hints/build_public_data_hints.ts new file mode 100644 index 00000000000..22d69a520bb --- /dev/null +++ b/yarn-project/circuits.js/src/hints/build_public_data_hints.ts @@ -0,0 +1,49 @@ +import { padArrayEnd } from '@aztec/foundation/collection'; +import { Fr } from '@aztec/foundation/fields'; +import { type Tuple } from '@aztec/foundation/serialize'; + +import { + MAX_PUBLIC_DATA_HINTS, + type MAX_PUBLIC_DATA_READS_PER_TX, + type MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + type PUBLIC_DATA_TREE_HEIGHT, +} from '../constants.gen.js'; +import { + type PublicDataRead, + type PublicDataTreeLeafPreimage, + type PublicDataUpdateRequest, +} from '../structs/index.js'; +import { type MembershipWitness } from '../structs/membership_witness.js'; +import { PublicDataHint } from '../structs/public_data_hint.js'; + +interface PublicDataMembershipWitnessWithPreimage { + membershipWitness: MembershipWitness; + leafPreimage: PublicDataTreeLeafPreimage; +} + +export async function buildPublicDataHints( + oracle: { + getMatchOrLowPublicDataMembershipWitness(leafSlot: bigint): Promise; + }, + publicDataReads: Tuple, + publicDataUpdateRequests: Tuple, +) { + const publicDataLeafSlotSet: Set = new Set(); + [...publicDataReads, ...publicDataUpdateRequests] + .filter(r => !r.isEmpty()) + .forEach(v => { + publicDataLeafSlotSet.add(v.leafSlot.toBigInt()); + }); + const uniquePublicDataLeafSlots = [...publicDataLeafSlotSet]; + + const hints: PublicDataHint[] = []; + for (let i = 0; i < uniquePublicDataLeafSlots.length; i++) { + const leafSlot = uniquePublicDataLeafSlots[i]; + const { membershipWitness, leafPreimage } = await oracle.getMatchOrLowPublicDataMembershipWitness(leafSlot); + const exists = leafPreimage.slot.toBigInt() === leafSlot; + const value = exists ? leafPreimage.value : Fr.ZERO; + hints.push(new PublicDataHint(new Fr(leafSlot), value, 0, membershipWitness, leafPreimage)); + } + + return padArrayEnd(hints, PublicDataHint.empty(), MAX_PUBLIC_DATA_HINTS); +} diff --git a/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts b/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts new file mode 100644 index 00000000000..164256ede3e --- /dev/null +++ b/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.test.ts @@ -0,0 +1,150 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { padArrayEnd } from '@aztec/foundation/collection'; +import { Fr } from '@aztec/foundation/fields'; +import { type Tuple } from '@aztec/foundation/serialize'; + +import { + MAX_PUBLIC_DATA_HINTS, + MAX_PUBLIC_DATA_READS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, +} from '../constants.gen.js'; +import { + LeafDataReadHint, + PendingReadHint, + PublicDataHint, + PublicDataRead, + PublicDataUpdateRequest, + ReadRequestStatus, +} from '../structs/index.js'; +import { buildPublicDataReadRequestHints } from './build_public_data_read_request_hints.js'; + +describe('buildPublicDataReadRequestHints', () => { + let publicDataReads: Tuple; + let expectedStatuses: Tuple; + let expectedPendingHints: Tuple; + let expectedLeafDataHints: Tuple; + + const makePublicDataWrite = (leafSlot: number, value: number) => + new PublicDataUpdateRequest(new Fr(leafSlot), new Fr(value)); + const makePublicDataHint = (slot: number, value: number) => { + const hint = PublicDataHint.empty(); + hint.leafSlot = new Fr(slot); + hint.value = new Fr(value); + return hint; + }; + const makePublicDataRead = (leafSlot: number, value: number) => new PublicDataRead(new Fr(leafSlot), new Fr(value)); + const makePendingHint = (readRequestIndex: number, hintIndex: number) => + new PendingReadHint(readRequestIndex, hintIndex); + const makeLeafDataHint = (readRequestIndex: number, hintIndex: number) => + new LeafDataReadHint(readRequestIndex, hintIndex); + + const publicDataUpdateRequests = padArrayEnd( + [makePublicDataWrite(55, 5555), makePublicDataWrite(77, 7777), makePublicDataWrite(99, 9999)], + PublicDataUpdateRequest.empty(), + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + ); + + const publicDataHints = padArrayEnd( + [ + makePublicDataHint(11, 100), + makePublicDataHint(22, 200), + makePublicDataHint(33, 300), + makePublicDataHint(55, 500), + makePublicDataHint(77, 0), + makePublicDataHint(99, 900), + ], + PublicDataHint.empty(), + MAX_PUBLIC_DATA_HINTS, + ); + + const buildHints = () => buildPublicDataReadRequestHints(publicDataReads, publicDataUpdateRequests, publicDataHints); + + const buildAndCheckHints = () => { + const hints = buildHints(); + expect(hints.readRequestStatuses).toEqual(expectedStatuses); + expect(hints.pendingReadHints).toEqual(expectedPendingHints); + expect(hints.leafDataReadHints).toEqual(expectedLeafDataHints); + }; + + beforeEach(() => { + publicDataReads = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty); + expectedStatuses = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, ReadRequestStatus.nada); + expectedPendingHints = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => + PendingReadHint.nada(MAX_PUBLIC_DATA_READS_PER_TX), + ); + expectedLeafDataHints = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => + LeafDataReadHint.nada(MAX_PUBLIC_DATA_READS_PER_TX), + ); + }); + + it('returns empty hints', () => { + buildAndCheckHints(); + }); + + it('builds hints for reading pending values', () => { + publicDataReads[0] = makePublicDataRead(77, 7777); + publicDataReads[1] = makePublicDataRead(99, 9999); + publicDataReads[2] = makePublicDataRead(55, 5555); + expectedStatuses[0] = ReadRequestStatus.pending(0); + expectedStatuses[1] = ReadRequestStatus.pending(1); + expectedStatuses[2] = ReadRequestStatus.pending(2); + expectedPendingHints[0] = makePendingHint(0, 1); + expectedPendingHints[1] = makePendingHint(1, 2); + expectedPendingHints[2] = makePendingHint(2, 0); + + buildAndCheckHints(); + }); + + it('builds hints for reading settled or uninitialized values', () => { + publicDataReads[0] = makePublicDataRead(33, 300); + publicDataReads[1] = makePublicDataRead(77, 0); + publicDataReads[2] = makePublicDataRead(55, 500); + publicDataReads[3] = makePublicDataRead(11, 100); + expectedStatuses[0] = ReadRequestStatus.settled(0); + expectedStatuses[1] = ReadRequestStatus.settled(1); + expectedStatuses[2] = ReadRequestStatus.settled(2); + expectedStatuses[3] = ReadRequestStatus.settled(3); + expectedLeafDataHints[0] = makeLeafDataHint(0, 2); + expectedLeafDataHints[1] = makeLeafDataHint(1, 4); + expectedLeafDataHints[2] = makeLeafDataHint(2, 3); + expectedLeafDataHints[3] = makeLeafDataHint(3, 0); + + buildAndCheckHints(); + }); + + it('builds hints for reading pending and settled values', () => { + publicDataReads[0] = makePublicDataRead(55, 500); + publicDataReads[1] = makePublicDataRead(55, 5555); + publicDataReads[2] = makePublicDataRead(77, 0); + publicDataReads[3] = makePublicDataRead(11, 100); + publicDataReads[4] = makePublicDataRead(99, 9999); + publicDataReads[5] = makePublicDataRead(77, 7777); + publicDataReads[6] = makePublicDataRead(11, 100); + expectedStatuses[0] = ReadRequestStatus.settled(0); + expectedStatuses[1] = ReadRequestStatus.pending(0); + expectedStatuses[2] = ReadRequestStatus.settled(1); + expectedStatuses[3] = ReadRequestStatus.settled(2); + expectedStatuses[4] = ReadRequestStatus.pending(1); + expectedStatuses[5] = ReadRequestStatus.pending(2); + expectedStatuses[6] = ReadRequestStatus.settled(3); + expectedPendingHints[0] = makePendingHint(1, 0); + expectedPendingHints[1] = makePendingHint(4, 2); + expectedPendingHints[2] = makePendingHint(5, 1); + expectedLeafDataHints[0] = makeLeafDataHint(0, 3); + expectedLeafDataHints[1] = makeLeafDataHint(2, 4); + expectedLeafDataHints[2] = makeLeafDataHint(3, 0); + expectedLeafDataHints[3] = makeLeafDataHint(6, 0); + + buildAndCheckHints(); + }); + + it('throws if reading unknown slot', () => { + publicDataReads[0] = makePublicDataRead(123, 100); + expect(() => buildHints()).toThrow('Cannot find a pending write or a data hint for the read request.'); + }); + + it('throws if reading unknown value', () => { + publicDataReads[0] = makePublicDataRead(11, 1111); + expect(() => buildHints()).toThrow('Value being read does not match existing public data or pending writes.'); + }); +}); diff --git a/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.ts b/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.ts new file mode 100644 index 00000000000..4f7b15f312b --- /dev/null +++ b/yarn-project/circuits.js/src/hints/build_public_data_read_request_hints.ts @@ -0,0 +1,45 @@ +import { type Tuple } from '@aztec/foundation/serialize'; + +import { + type MAX_PUBLIC_DATA_HINTS, + type MAX_PUBLIC_DATA_READS_PER_TX, + type MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, +} from '../constants.gen.js'; +import { + type PublicDataRead, + PublicDataReadRequestHintsBuilder, + type PublicDataUpdateRequest, +} from '../structs/index.js'; +import { type PublicDataHint } from '../structs/public_data_hint.js'; +import { countAccumulatedItems } from '../utils/index.js'; + +export function buildPublicDataReadRequestHints( + publicDataReads: Tuple, + publicDataUpdateRequests: Tuple, + publicDataHints: Tuple, +) { + const builder = new PublicDataReadRequestHintsBuilder(); + + const numReadRequests = countAccumulatedItems(publicDataReads); + for (let i = 0; i < numReadRequests; ++i) { + const rr = publicDataReads[i]; + // TODO: Add counters to reads and writes. + const writeIndex = publicDataUpdateRequests.findIndex( + w => w.leafSlot.equals(rr.leafSlot) && w.newValue.equals(rr.value), + ); + if (writeIndex !== -1) { + builder.addPendingReadRequest(i, writeIndex); + } else { + const hintIndex = publicDataHints.findIndex(h => h.leafSlot.equals(rr.leafSlot)); + if (hintIndex === -1) { + throw new Error('Cannot find a pending write or a data hint for the read request.'); + } + if (!publicDataHints[hintIndex].value.equals(rr.value)) { + throw new Error('Value being read does not match existing public data or pending writes.'); + } + builder.addLeafDataReadRequest(i, hintIndex); + } + } + + return builder.toHints(); +} diff --git a/yarn-project/circuits.js/src/hints/index.ts b/yarn-project/circuits.js/src/hints/index.ts index 476edce05e9..d9378ed85b5 100644 --- a/yarn-project/circuits.js/src/hints/index.ts +++ b/yarn-project/circuits.js/src/hints/index.ts @@ -1,2 +1,3 @@ export * from './build_hints.js'; -export * from '../utils/index.js'; +export * from './build_public_data_hints.js'; +export * from './build_public_data_read_request_hints.js'; diff --git a/yarn-project/circuits.js/src/index.ts b/yarn-project/circuits.js/src/index.ts index 3b6fdbcd0e6..d4c939ef836 100644 --- a/yarn-project/circuits.js/src/index.ts +++ b/yarn-project/circuits.js/src/index.ts @@ -6,3 +6,4 @@ export * from './interfaces/index.js'; export * from './keys/index.js'; export * from './structs/index.js'; export * from './types/index.js'; +export * from './utils/index.js'; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap index f718c7fb3b1..46d4e2bf80d 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_call_stack_item.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x243b1b69ea529d158803cc7a16b52293c5e5f2a1859337e3f69e4b20f55c6fb6>`; +exports[`PrivateCallStackItem computes empty item hash 1`] = `Fr<0x24185d8e88fe796dec6e400f3d6c7572cefd85cea80591f268f08a9350992c48>`; -exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x230cf9e8515b74f4dd60fcf3a32c59d1efd2a704966a72838f1d88b86bcecfc0>`; +exports[`PrivateCallStackItem computes hash 1`] = `Fr<0x2e5307580ef277146cc3c6a9d9210c6e317d9b6a033755f509e6161d0eaf576a>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap index 72e4d887dfe..4e423c22442 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/private_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x02e09d8c4897d560bd4caf05ab45fa22e1d4a251bf5b5e0448310a7f40f7a0b8>`; +exports[`PrivateCircuitPublicInputs computes empty inputs hash 1`] = `Fr<0x24ea9ab3fc039778bef8e7212f6a09feec1019db19b449333b523a08b812ee88>`; -exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x1b87232023a3accb0f63ffaa41068972b98185c62bf1542cebd77c8bedfd5313>`; +exports[`PrivateCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x144c861f88d1ba68fc7e72f7a578546207bbf785e4a23278601662d85cd25d12>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap index 6b17402df69..230870d273c 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_call_stack_item.test.ts.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x0864975afc9bec7eb7ec5b5608bbef648ec9afead1bbe986d0af148e3c944b9b"`; +exports[`PublicCallStackItem Computes a callstack item hash 1`] = `"0x0c0d60d424315af5f106a802b250c27c613a9ec1c0f583c6ad806cf22fe66a13"`; -exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x12c634ebadf4209e2def6cac0753f151422faf11237dc4f136bc17a84c8c2d76"`; +exports[`PublicCallStackItem Computes a callstack item request hash 1`] = `"0x134d01b778664dbc1ffa953008ce28f72b0cb258533776f10df59a59d791e972"`; -exports[`PublicCallStackItem computes hash 1`] = `Fr<0x1fcf20622dc0bed7c461128afb302fd60a54628a1a5daf2e157bbacf413342a2>`; +exports[`PublicCallStackItem computes hash 1`] = `Fr<0x2c7d4c31cdb4762c88686417968228c7d102e205e89cb157a34365eef5bfb15c>`; diff --git a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap index d3cb2b628a1..057d7b9aeac 100644 --- a/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap +++ b/yarn-project/circuits.js/src/structs/__snapshots__/public_circuit_public_inputs.test.ts.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PublicCircuitPublicInputs computes empty item hash 1`] = `Fr<0x00147d3d2cde08ee1046bf73cb6664c2bdf11b43c5dca0e72f4137f354bdad25>`; +exports[`PublicCircuitPublicInputs computes empty item hash 1`] = `Fr<0x1092820bc987359300ff136abf020d58218e1b3484e03d756c76e81ac56ccbf7>`; -exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x010f05c698115df7a51edde4b5580dde0fa0598492ab4f22faf82b02db0a9230>`; +exports[`PublicCircuitPublicInputs hash matches snapshot 1`] = `Fr<0x251dcf0ab2afb050857487a1545e99cc12ddd7655154f89b8aab1d7872845173>`; diff --git a/yarn-project/circuits.js/src/structs/contract_storage_read.ts b/yarn-project/circuits.js/src/structs/contract_storage_read.ts index 2c376a1d3f5..52d708f0ef1 100644 --- a/yarn-project/circuits.js/src/structs/contract_storage_read.ts +++ b/yarn-project/circuits.js/src/structs/contract_storage_read.ts @@ -1,3 +1,4 @@ +import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; @@ -24,6 +25,7 @@ export class ContractStorageRead { * Note: Not serialized */ public readonly sideEffectCounter?: number, + public contractAddress?: AztecAddress, // TODO: Should not be optional. This is a temporary hack to silo the storage slot with the correct address for nested executions. ) {} static from(args: { @@ -39,8 +41,9 @@ export class ContractStorageRead { * Optional side effect counter tracking position of this event in tx execution. */ sideEffectCounter?: number; + contractAddress?: AztecAddress; }) { - return new ContractStorageRead(args.storageSlot, args.currentValue, args.sideEffectCounter); + return new ContractStorageRead(args.storageSlot, args.currentValue, args.sideEffectCounter, args.contractAddress); } toBuffer() { diff --git a/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts b/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts index 8508fa8c7b8..378279d55bb 100644 --- a/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts +++ b/yarn-project/circuits.js/src/structs/contract_storage_update_request.ts @@ -1,3 +1,4 @@ +import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; @@ -24,6 +25,7 @@ export class ContractStorageUpdateRequest { * Optional side effect counter tracking position of this event in tx execution. */ public readonly sideEffectCounter?: number, + public contractAddress?: AztecAddress, // TODO: Should not be optional. This is a temporary hack to silo the storage slot with the correct address for nested executions. ) {} toBuffer() { @@ -50,7 +52,7 @@ export class ContractStorageUpdateRequest { * @returns The array. */ static getFields(fields: FieldsOf) { - return [fields.storageSlot, fields.newValue, fields.sideEffectCounter] as const; + return [fields.storageSlot, fields.newValue, fields.sideEffectCounter, fields.contractAddress] as const; } static empty() { diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index da3ec5a2c96..400c60e8ac9 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -47,7 +47,9 @@ export * from './proof.js'; export * from './public_call_request.js'; export * from './public_call_stack_item.js'; export * from './public_circuit_public_inputs.js'; +export * from './public_data_hint.js'; export * from './public_data_read_request.js'; +export * from './public_data_read_request_hints.js'; export * from './public_data_update_request.js'; export * from './read_request.js'; export * from './read_request_hints.js'; diff --git a/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts index cb59c58b76d..84637a61f91 100644 --- a/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/kernel_circuit_public_inputs.ts @@ -1,6 +1,7 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { AggregationObject } from '../aggregation_object.js'; +import { PartialStateReference } from '../partial_state_reference.js'; import { RevertCode } from '../revert_code.js'; import { RollupValidationRequests } from '../rollup_validation_requests.js'; import { CombinedAccumulatedData } from './combined_accumulated_data.js'; @@ -28,6 +29,7 @@ export class KernelCircuitPublicInputs { * Data which is not modified by the circuits. */ public constants: CombinedConstantData, + public startState: PartialStateReference, /** * Flag indicating whether the transaction reverted. */ @@ -44,6 +46,7 @@ export class KernelCircuitPublicInputs { this.rollupValidationRequests, this.end, this.constants, + this.startState, this.revertCode, ); } @@ -60,6 +63,7 @@ export class KernelCircuitPublicInputs { reader.readObject(RollupValidationRequests), reader.readObject(CombinedAccumulatedData), reader.readObject(CombinedConstantData), + reader.readObject(PartialStateReference), reader.readObject(RevertCode), ); } @@ -70,6 +74,7 @@ export class KernelCircuitPublicInputs { RollupValidationRequests.empty(), CombinedAccumulatedData.empty(), CombinedConstantData.empty(), + PartialStateReference.empty(), RevertCode.OK, ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts index 909f1afe796..d52cc104bc7 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_accumulated_data.ts @@ -3,12 +3,14 @@ import { Fr } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { + MAX_ENCRYPTED_LOGS_PER_TX, type MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { Gas } from '../gas.js'; @@ -36,12 +38,12 @@ export class PrivateAccumulatedData { * Accumulated encrypted logs hash from all the previous kernel iterations. * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. */ - public encryptedLogsHash: Fr, + public encryptedLogsHashes: Tuple, /** * Accumulated unencrypted logs hash from all the previous kernel iterations. * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. */ - public unencryptedLogsHash: Fr, + public unencryptedLogsHashes: Tuple, /** * Total accumulated length of the encrypted log preimages emitted in all the previous kernel iterations */ @@ -69,8 +71,8 @@ export class PrivateAccumulatedData { this.newNoteHashes, this.newNullifiers, this.newL2ToL1Msgs, - this.encryptedLogsHash, - this.unencryptedLogsHash, + this.encryptedLogsHashes, + this.unencryptedLogsHashes, this.encryptedLogPreimagesLength, this.unencryptedLogPreimagesLength, this.privateCallStack, @@ -94,8 +96,8 @@ export class PrivateAccumulatedData { reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, SideEffect), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr), - Fr.fromBuffer(reader), - Fr.fromBuffer(reader), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readArray(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, CallRequest), @@ -118,8 +120,8 @@ export class PrivateAccumulatedData { makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, SideEffect.empty), makeTuple(MAX_NEW_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash.empty), makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.zero), - Fr.zero(), - Fr.zero(), + makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect.empty), Fr.zero(), Fr.zero(), makeTuple(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, CallRequest.empty), diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts index cabf3d15f7f..561b3bf0b25 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_private_inputs.ts @@ -2,10 +2,12 @@ import { Fr, GrumpkinScalar } from '@aztec/foundation/fields'; import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { + MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_TX, MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { type GrumpkinPrivateKey } from '../../types/grumpkin_private_key.js'; import { countAccumulatedItems } from '../../utils/index.js'; @@ -50,6 +52,22 @@ export class PrivateKernelTailCircuitPrivateInputs { * Contains hints for the transient nullifiers to localize corresponding commitments. */ public nullifierCommitmentHints: Tuple, + /** + * The sorted encrypted log hashes. + */ + public sortedEncryptedLogHashes: Tuple, + /** + * The sorted encrypted log hashes indexes. Maps original to sorted. + */ + public sortedEncryptedLogHashesIndexes: Tuple, + /** + * The sorted unencrypted log hashes. + */ + public sortedUnencryptedLogHashes: Tuple, + /** + * The sorted encrypted log hashes indexes. Maps original to sorted. + */ + public sortedUnencryptedLogHashesIndexes: Tuple, /** * The master nullifier secret keys for the nullifier key validation requests. */ @@ -74,6 +92,10 @@ export class PrivateKernelTailCircuitPrivateInputs { this.sortedNewNullifiersIndexes, this.nullifierReadRequestHints, this.nullifierCommitmentHints, + this.sortedEncryptedLogHashes, + this.sortedEncryptedLogHashesIndexes, + this.sortedUnencryptedLogHashes, + this.sortedUnencryptedLogHashesIndexes, this.masterNullifierSecretKeys, ); } @@ -94,6 +116,10 @@ export class PrivateKernelTailCircuitPrivateInputs { reader.readNumbers(MAX_NEW_NULLIFIERS_PER_TX), reader.readObject({ fromBuffer: nullifierReadRequestHintsFromBuffer }), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, Fr), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), + reader.readNumbers(MAX_ENCRYPTED_LOGS_PER_TX), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), + reader.readNumbers(MAX_UNENCRYPTED_LOGS_PER_TX), reader.readArray(MAX_NULLIFIER_KEY_VALIDATION_REQUESTS_PER_TX, GrumpkinScalar), ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts index cc7ac7fb8b4..f064b5ee6ec 100644 --- a/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/private_kernel_tail_circuit_public_inputs.ts @@ -3,6 +3,7 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { MAX_NEW_NULLIFIERS_PER_TX } from '../../constants.gen.js'; import { countAccumulatedItems, mergeAccumulatedData } from '../../utils/index.js'; import { AggregationObject } from '../aggregation_object.js'; +import { PartialStateReference } from '../partial_state_reference.js'; import { RevertCode } from '../revert_code.js'; import { RollupValidationRequests } from '../rollup_validation_requests.js'; import { ValidationRequests } from '../validation_requests.js'; @@ -135,6 +136,7 @@ export class PrivateKernelTailCircuitPublicInputs { this.forRollup.rollupValidationRequests, this.forRollup.end, this.constants, + PartialStateReference.empty(), this.revertCode, ); } diff --git a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts index 21d94842d5a..7173ba93f71 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_accumulated_data.ts @@ -5,12 +5,14 @@ import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/s import { inspect } from 'util'; import { + MAX_ENCRYPTED_LOGS_PER_TX, type MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, } from '../../constants.gen.js'; import { CallRequest } from '../call_request.js'; import { Gas } from '../gas.js'; @@ -35,12 +37,12 @@ export class PublicAccumulatedData { * Accumulated encrypted logs hash from all the previous kernel iterations. * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. */ - public encryptedLogsHash: Fr, + public encryptedLogsHashes: Tuple, /** * Accumulated unencrypted logs hash from all the previous kernel iterations. * Note: Represented as a tuple of 2 fields in order to fit in all of the 256 bits of sha256 hash. */ - public unencryptedLogsHash: Fr, + public unencryptedLogsHashes: Tuple, /** * Total accumulated length of the encrypted log preimages emitted in all the previous kernel iterations */ @@ -67,8 +69,8 @@ export class PublicAccumulatedData { this.newNoteHashes, this.newNullifiers, this.newL2ToL1Msgs, - this.encryptedLogsHash, - this.unencryptedLogsHash, + this.encryptedLogsHashes, + this.unencryptedLogsHashes, this.encryptedLogPreimagesLength, this.unencryptedLogPreimagesLength, this.publicDataUpdateRequests, @@ -86,8 +88,8 @@ export class PublicAccumulatedData { this.newNoteHashes.every(x => x.isEmpty()) && this.newNullifiers.every(x => x.isEmpty()) && this.newL2ToL1Msgs.every(x => x.isZero()) && - this.encryptedLogsHash.isZero() && - this.unencryptedLogsHash.isZero() && + this.encryptedLogsHashes.every(x => x.isEmpty()) && + this.unencryptedLogsHashes.every(x => x.isEmpty()) && this.encryptedLogPreimagesLength.isZero() && this.unencryptedLogPreimagesLength.isZero() && this.publicDataUpdateRequests.every(x => x.isEmpty()) && @@ -102,8 +104,8 @@ export class PublicAccumulatedData { newNoteHashes: [${this.newNoteHashes.map(h => h.toString()).join(', ')}], newNullifiers: [${this.newNullifiers.map(h => h.toString()).join(', ')}], newL2ToL1Msgs: [${this.newL2ToL1Msgs.map(h => h.toString()).join(', ')}], - encryptedLogsHash: [${this.encryptedLogsHash}], - unencryptedLogsHash: [${this.unencryptedLogsHash}], + encryptedLogsHashes: [${this.encryptedLogsHashes.map(h => h.toString()).join(', ')}], + unencryptedLogsHashes: [${this.unencryptedLogsHashes.map(h => h.toString()).join(', ')}], encryptedLogPreimagesLength: ${this.encryptedLogPreimagesLength} unencryptedLogPreimagesLength: ${this.unencryptedLogPreimagesLength} publicDataUpdateRequests: [${this.publicDataUpdateRequests.map(h => h.toString()).join(', ')}], @@ -123,8 +125,8 @@ export class PublicAccumulatedData { reader.readArray(MAX_NEW_NOTE_HASHES_PER_TX, SideEffect), reader.readArray(MAX_NEW_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash), reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr), - Fr.fromBuffer(reader), - Fr.fromBuffer(reader), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect), Fr.fromBuffer(reader), Fr.fromBuffer(reader), reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest), @@ -147,8 +149,8 @@ export class PublicAccumulatedData { makeTuple(MAX_NEW_NOTE_HASHES_PER_TX, SideEffect.empty), makeTuple(MAX_NEW_NULLIFIERS_PER_TX, SideEffectLinkedToNoteHash.empty), makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_TX, Fr.zero), - Fr.zero(), - Fr.zero(), + makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, SideEffect.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, SideEffect.empty), Fr.zero(), Fr.zero(), makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty), diff --git a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts index be3037d4565..5399146b7e5 100644 --- a/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts +++ b/yarn-project/circuits.js/src/structs/kernel/public_kernel_tail_circuit_private_inputs.ts @@ -1,15 +1,16 @@ -import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; +import { MAX_PUBLIC_DATA_HINTS } from '../../constants.gen.js'; import { type NullifierNonExistentReadRequestHints, nullifierNonExistentReadRequestHintsFromBuffer, } from '../non_existent_read_request_hints.js'; +import { PartialStateReference } from '../partial_state_reference.js'; +import { PublicDataHint } from '../public_data_hint.js'; +import { PublicDataReadRequestHints } from '../public_data_read_request_hints.js'; import { type NullifierReadRequestHints, nullifierReadRequestHintsFromBuffer } from '../read_request_hints.js'; import { PublicKernelData } from './public_kernel_data.js'; -/** - * Inputs to the public kernel circuit. - */ export class PublicKernelTailCircuitPrivateInputs { constructor( /** @@ -24,6 +25,9 @@ export class PublicKernelTailCircuitPrivateInputs { * Contains hints for the nullifier non existent read requests. */ public readonly nullifierNonExistentReadRequestHints: NullifierNonExistentReadRequestHints, + public readonly publicDataHints: Tuple, + public readonly publicDataReadRequestHints: PublicDataReadRequestHints, + public readonly startState: PartialStateReference, ) {} toBuffer() { @@ -31,6 +35,9 @@ export class PublicKernelTailCircuitPrivateInputs { this.previousKernel, this.nullifierReadRequestHints, this.nullifierNonExistentReadRequestHints, + this.publicDataHints, + this.publicDataReadRequestHints, + this.startState, ); } @@ -40,6 +47,9 @@ export class PublicKernelTailCircuitPrivateInputs { reader.readObject(PublicKernelData), nullifierReadRequestHintsFromBuffer(reader), nullifierNonExistentReadRequestHintsFromBuffer(reader), + reader.readArray(MAX_PUBLIC_DATA_HINTS, PublicDataHint), + reader.readObject(PublicDataReadRequestHints), + reader.readObject(PartialStateReference), ); } diff --git a/yarn-project/circuits.js/src/structs/membership_witness.ts b/yarn-project/circuits.js/src/structs/membership_witness.ts index db0457ef394..fd623300be1 100644 --- a/yarn-project/circuits.js/src/structs/membership_witness.ts +++ b/yarn-project/circuits.js/src/structs/membership_witness.ts @@ -49,7 +49,7 @@ export class MembershipWitness { * @param leafIndex - Index of the leaf in the Merkle tree. * @returns Membership witness with zero sibling path. */ - public static empty(pathSize: N, leafIndex: bigint): MembershipWitness { + public static empty(pathSize: N, leafIndex = 0n): MembershipWitness { const arr = Array(pathSize) .fill(0) .map(() => Fr.ZERO) as Tuple; diff --git a/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts b/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts index 9659c63d0c3..faea5129fbb 100644 --- a/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts +++ b/yarn-project/circuits.js/src/structs/non_existent_read_request_hints.ts @@ -18,7 +18,7 @@ export class NonMembershipHint LEAF_PREIMAGE, ) { - return new NonMembershipHint(MembershipWitness.empty(treeHeight, 0n), makeEmptyLeafPreimage()); + return new NonMembershipHint(MembershipWitness.empty(treeHeight), makeEmptyLeafPreimage()); } static fromBuffer( diff --git a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts index 95e6dc6715c..981f7263059 100644 --- a/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/private_circuit_public_inputs.ts @@ -13,6 +13,7 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { GeneratorIndex, + MAX_ENCRYPTED_LOGS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_NOTE_HASHES_PER_CALL, MAX_NEW_NULLIFIERS_PER_CALL, @@ -21,6 +22,7 @@ import { MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, + MAX_UNENCRYPTED_LOGS_PER_CALL, PRIVATE_CIRCUIT_PUBLIC_INPUTS_LENGTH, } from '../constants.gen.js'; import { Header } from '../structs/header.js'; @@ -104,12 +106,12 @@ export class PrivateCircuitPublicInputs { * Hash of the encrypted logs emitted in this function call. * Note: Truncated to 31 bytes to fit in Fr. */ - public encryptedLogsHash: Fr, + public encryptedLogsHashes: Tuple, /** * Hash of the unencrypted logs emitted in this function call. * Note: Truncated to 31 bytes to fit in Fr. */ - public unencryptedLogsHash: Fr, + public unencryptedLogsHashes: Tuple, /** * Length of the encrypted log preimages emitted in this function call. * Note: Here so that the gas cost of this request can be measured by circuits, without actually needing to feed @@ -170,8 +172,8 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), - reader.readObject(Fr), - reader.readObject(Fr), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_CALL, SideEffect), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect), reader.readObject(Fr), reader.readObject(Fr), reader.readObject(Header), @@ -198,8 +200,8 @@ export class PrivateCircuitPublicInputs { reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), - reader.readField(), - reader.readField(), + reader.readArray(MAX_ENCRYPTED_LOGS_PER_CALL, SideEffect), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect), reader.readField(), reader.readField(), reader.readObject(Header), @@ -229,8 +231,8 @@ export class PrivateCircuitPublicInputs { makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, - Fr.ZERO, - Fr.ZERO, + makeTuple(MAX_ENCRYPTED_LOGS_PER_CALL, SideEffect.empty), + makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect.empty), Fr.ZERO, Fr.ZERO, Header.empty(), @@ -258,8 +260,8 @@ export class PrivateCircuitPublicInputs { isZeroArray(this.privateCallStackHashes) && isZeroArray(this.publicCallStackHashes) && isEmptyArray(this.newL2ToL1Msgs) && - this.encryptedLogsHash.isZero() && - this.unencryptedLogsHash.isZero() && + isEmptyArray(this.encryptedLogsHashes) && + isEmptyArray(this.unencryptedLogsHashes) && this.encryptedLogPreimagesLength.isZero() && this.unencryptedLogPreimagesLength.isZero() && this.historicalHeader.isEmpty() && @@ -290,8 +292,8 @@ export class PrivateCircuitPublicInputs { fields.newL2ToL1Msgs, fields.startSideEffectCounter, fields.endSideEffectCounter, - fields.encryptedLogsHash, - fields.unencryptedLogsHash, + fields.encryptedLogsHashes, + fields.unencryptedLogsHashes, fields.encryptedLogPreimagesLength, fields.unencryptedLogPreimagesLength, fields.historicalHeader, diff --git a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts index 9c2c5c65a4f..df93a84cd24 100644 --- a/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/public_circuit_public_inputs.ts @@ -22,6 +22,7 @@ import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, + MAX_UNENCRYPTED_LOGS_PER_CALL, PUBLIC_CIRCUIT_PUBLIC_INPUTS_LENGTH, } from '../constants.gen.js'; import { CallContext } from './call_context.js'; @@ -101,7 +102,7 @@ export class PublicCircuitPublicInputs { * Hash of the unencrypted logs emitted in this function call. * Note: Truncated to 31 bytes to fit in Fr. */ - public unencryptedLogsHash: Fr, + public unencryptedLogsHashes: Tuple, /** * Length of the unencrypted log preimages emitted in this function call. */ @@ -153,7 +154,7 @@ export class PublicCircuitPublicInputs { makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message.empty), Fr.ZERO, Fr.ZERO, - Fr.ZERO, + makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect.empty), Fr.ZERO, Header.empty(), AztecAddress.ZERO, @@ -181,7 +182,7 @@ export class PublicCircuitPublicInputs { isArrayEmpty(this.newL2ToL1Msgs, item => item.isEmpty()) && this.startSideEffectCounter.isZero() && this.endSideEffectCounter.isZero() && - this.unencryptedLogsHash.isZero() && + isArrayEmpty(this.unencryptedLogsHashes, item => item.isEmpty()) && this.unencryptedLogPreimagesLength.isZero() && this.historicalHeader.isEmpty() && this.proverAddress.isZero() && @@ -210,7 +211,7 @@ export class PublicCircuitPublicInputs { fields.newL2ToL1Msgs, fields.startSideEffectCounter, fields.endSideEffectCounter, - fields.unencryptedLogsHash, + fields.unencryptedLogsHashes, fields.unencryptedLogPreimagesLength, fields.historicalHeader, fields.proverAddress, @@ -258,7 +259,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readObject(Fr), reader.readObject(Fr), - reader.readObject(Fr), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect), reader.readObject(Fr), reader.readObject(Header), reader.readObject(AztecAddress), @@ -284,7 +285,7 @@ export class PublicCircuitPublicInputs { reader.readArray(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, L2ToL1Message), reader.readField(), reader.readField(), - reader.readField(), + reader.readArray(MAX_UNENCRYPTED_LOGS_PER_CALL, SideEffect), reader.readField(), Header.fromFields(reader), AztecAddress.fromFields(reader), diff --git a/yarn-project/circuits.js/src/structs/public_data_hint.ts b/yarn-project/circuits.js/src/structs/public_data_hint.ts new file mode 100644 index 00000000000..52d73a080f0 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/public_data_hint.ts @@ -0,0 +1,47 @@ +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { PUBLIC_DATA_TREE_HEIGHT } from '../constants.gen.js'; +import { MembershipWitness } from './membership_witness.js'; +import { PublicDataTreeLeafPreimage } from './rollup/public_data_leaf/index.js'; + +export class PublicDataHint { + constructor( + public leafSlot: Fr, + public value: Fr, + public overrideCounter: number, + public membershipWitness: MembershipWitness, + public leafPreimage: PublicDataTreeLeafPreimage, + ) {} + + static empty() { + return new PublicDataHint( + Fr.ZERO, + Fr.ZERO, + 0, + MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT), + PublicDataTreeLeafPreimage.empty(), + ); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicDataHint( + reader.readObject(Fr), + reader.readObject(Fr), + reader.readNumber(), + MembershipWitness.fromBuffer(reader, PUBLIC_DATA_TREE_HEIGHT), + reader.readObject(PublicDataTreeLeafPreimage), + ); + } + + toBuffer() { + return serializeToBuffer( + this.leafSlot, + this.value, + this.overrideCounter, + this.membershipWitness, + this.leafPreimage, + ); + } +} diff --git a/yarn-project/circuits.js/src/structs/public_data_read_request_hints.ts b/yarn-project/circuits.js/src/structs/public_data_read_request_hints.ts new file mode 100644 index 00000000000..8c6b324d63f --- /dev/null +++ b/yarn-project/circuits.js/src/structs/public_data_read_request_hints.ts @@ -0,0 +1,86 @@ +import { makeTuple } from '@aztec/foundation/array'; +import { BufferReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { MAX_PUBLIC_DATA_READS_PER_TX } from '../constants.gen.js'; +import { PendingReadHint, ReadRequestState, ReadRequestStatus } from './read_request_hints.js'; + +export class LeafDataReadHint { + constructor(public readRequestIndex: number, public dataHintIndex: number) {} + + static nada(readRequestLen: number) { + return new LeafDataReadHint(readRequestLen, 0); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new LeafDataReadHint(reader.readNumber(), reader.readNumber()); + } + + toBuffer() { + return serializeToBuffer(this.readRequestIndex, this.dataHintIndex); + } +} + +export class PublicDataReadRequestHints { + constructor( + public readRequestStatuses: Tuple, + public pendingReadHints: Tuple, + public leafDataReadHints: Tuple, + ) {} + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new PublicDataReadRequestHints( + reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, ReadRequestStatus), + reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PendingReadHint), + reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, LeafDataReadHint), + ); + } + + toBuffer() { + return serializeToBuffer(this.readRequestStatuses, this.pendingReadHints, this.leafDataReadHints); + } +} + +export class PublicDataReadRequestHintsBuilder { + private hints: PublicDataReadRequestHints; + private numPendingReadHints = 0; + private numLeafDataReadHints = 0; + + constructor() { + this.hints = new PublicDataReadRequestHints( + makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, ReadRequestStatus.nada), + makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => PendingReadHint.nada(MAX_PUBLIC_DATA_READS_PER_TX)), + makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => LeafDataReadHint.nada(MAX_PUBLIC_DATA_READS_PER_TX)), + ); + } + + static empty() { + return new PublicDataReadRequestHintsBuilder().toHints(); + } + + addPendingReadRequest(readRequestIndex: number, publicDataWriteIndex: number) { + this.hints.readRequestStatuses[readRequestIndex] = new ReadRequestStatus( + ReadRequestState.PENDING, + this.numPendingReadHints, + ); + this.hints.pendingReadHints[this.numPendingReadHints] = new PendingReadHint(readRequestIndex, publicDataWriteIndex); + this.numPendingReadHints++; + } + + addLeafDataReadRequest(readRequestIndex: number, leafDataDataHintIndex: number) { + this.hints.readRequestStatuses[readRequestIndex] = new ReadRequestStatus( + ReadRequestState.SETTLED, + this.numLeafDataReadHints, + ); + this.hints.leafDataReadHints[this.numLeafDataReadHints] = new LeafDataReadHint( + readRequestIndex, + leafDataDataHintIndex, + ); + this.numLeafDataReadHints++; + } + + toHints() { + return this.hints; + } +} diff --git a/yarn-project/circuits.js/src/structs/read_request_hints.ts b/yarn-project/circuits.js/src/structs/read_request_hints.ts index 6e6439ec426..fd0be737614 100644 --- a/yarn-project/circuits.js/src/structs/read_request_hints.ts +++ b/yarn-project/circuits.js/src/structs/read_request_hints.ts @@ -19,6 +19,14 @@ export class ReadRequestStatus { return new ReadRequestStatus(ReadRequestState.NADA, 0); } + static pending(hintIndex: number) { + return new ReadRequestStatus(ReadRequestState.PENDING, hintIndex); + } + + static settled(hintIndex: number) { + return new ReadRequestStatus(ReadRequestState.SETTLED, hintIndex); + } + static fromBuffer(buffer: Buffer | BufferReader) { const reader = BufferReader.asReader(buffer); return new ReadRequestStatus(reader.readNumber(), reader.readNumber()); @@ -58,7 +66,7 @@ export class SettledReadHint LEAF_PREIMAGE, ) { - return new SettledReadHint(readRequestLen, MembershipWitness.empty(treeHeight, 0n), emptyLeafPreimage()); + return new SettledReadHint(readRequestLen, MembershipWitness.empty(treeHeight), emptyLeafPreimage()); } static fromBuffer( diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 1a1c2473d6e..d6d99d49a5a 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -38,6 +38,8 @@ import { GrumpkinScalar, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, L2ToL1Message, + MAX_ENCRYPTED_LOGS_PER_CALL, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_CALL, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_CALL, @@ -56,10 +58,13 @@ import { MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, + MAX_PUBLIC_DATA_HINTS, MAX_PUBLIC_DATA_READS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_CALL, + MAX_UNENCRYPTED_LOGS_PER_TX, MaxBlockNumber, MembershipWitness, MergeRollupInputs, @@ -97,7 +102,9 @@ import { PublicCallRequest, PublicCallStackItem, PublicCircuitPublicInputs, + PublicDataHint, PublicDataRead, + PublicDataReadRequestHintsBuilder, PublicDataTreeLeaf, PublicDataTreeLeafPreimage, PublicDataUpdateRequest, @@ -336,8 +343,8 @@ export function makePublicAccumulatedData(seed = 1, full = false): PublicAccumul SideEffectLinkedToNoteHash.empty, ), tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), - fr(seed + 0x700), // encrypted logs hash - fr(seed + 0x800), // unencrypted logs hash + tupleGenerator(MAX_ENCRYPTED_LOGS_PER_TX, sideEffectFromNumber, seed + 0x700, SideEffect.empty), // encrypted logs hashes + tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, sideEffectFromNumber, seed + 0x800, SideEffect.empty), // unencrypted logs hashes fr(seed + 0x900), // encrypted_log_preimages_length fr(seed + 0xa00), // unencrypted_log_preimages_length tupleGenerator( @@ -368,8 +375,8 @@ export function makePrivateAccumulatedData(seed = 1, full = false) { SideEffectLinkedToNoteHash.empty, ), tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_TX, fr, seed + 0x600, Fr.zero), - fr(seed + 0x700), // encrypted logs hash - fr(seed + 0x800), // unencrypted logs hash + tupleGenerator(MAX_ENCRYPTED_LOGS_PER_TX, sideEffectFromNumber, seed + 0x700, SideEffect.empty), // encrypted logs hashes + tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_TX, sideEffectFromNumber, seed + 0x800, SideEffect.empty), // unencrypted logs hashes fr(seed + 0x900), // encrypted_log_preimages_length fr(seed + 0xa00), // unencrypted_log_preimages_length tupleGenerator(MAX_PRIVATE_CALL_STACK_LENGTH_PER_TX, makeCallRequest, seed + 0x400, CallRequest.empty), @@ -452,7 +459,7 @@ export function makePublicCircuitPublicInputs( tupleGenerator(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x900, L2ToL1Message.empty), fr(seed + 0xa00), fr(seed + 0xa01), - fr(seed + 0x901), + tupleGenerator(MAX_UNENCRYPTED_LOGS_PER_CALL, sideEffectFromNumber, seed + 0x901, SideEffect.empty), fr(seed + 0x902), makeHeader(seed + 0xa00, undefined), makeAztecAddress(seed + 0xb01), @@ -537,6 +544,7 @@ export function makeKernelCircuitPublicInputs(seed = 1, fullAccumulatedData = tr makeRollupValidationRequests(seed), makeCombinedAccumulatedData(seed, fullAccumulatedData), makeConstantData(seed + 0x100), + makePartialStateReference(seed + 0x200), RevertCode.OK, ); } @@ -791,6 +799,9 @@ export function makePublicKernelTailCircuitPrivateInputs(seed = 1): PublicKernel makePublicKernelData(seed), NullifierReadRequestHintsBuilder.empty(), NullifierNonExistentReadRequestHintsBuilder.empty(), + makeTuple(MAX_PUBLIC_DATA_HINTS, PublicDataHint.empty, seed + 0x100), + PublicDataReadRequestHintsBuilder.empty(), + makePartialStateReference(seed + 0x200), ); } @@ -904,8 +915,8 @@ export function makePrivateCircuitPublicInputs(seed = 0): PrivateCircuitPublicIn newL2ToL1Msgs: makeTuple(MAX_NEW_L2_TO_L1_MSGS_PER_CALL, makeL2ToL1Message, seed + 0x800), startSideEffectCounter: fr(seed + 0x849), endSideEffectCounter: fr(seed + 0x850), - encryptedLogsHash: fr(seed + 0x900), - unencryptedLogsHash: fr(seed + 0xa00), + encryptedLogsHashes: makeTuple(MAX_ENCRYPTED_LOGS_PER_CALL, sideEffectFromNumber, seed + 0x900), + unencryptedLogsHashes: makeTuple(MAX_UNENCRYPTED_LOGS_PER_CALL, sideEffectFromNumber, seed + 0xa00), encryptedLogPreimagesLength: fr(seed + 0xb00), unencryptedLogPreimagesLength: fr(seed + 0xc00), historicalHeader: makeHeader(seed + 0xd00, undefined), diff --git a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts index 2d4009042a0..c2bbcc8ceb8 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_tx_size_fees.test.ts @@ -8,7 +8,7 @@ import { PublicFeePaymentMethod, TxStatus, } from '@aztec/aztec.js'; -import { GasSettings } from '@aztec/circuits.js'; +import { Fr, GasSettings } from '@aztec/circuits.js'; import { FPCContract, GasTokenContract, TokenContract } from '@aztec/noir-contracts.js'; import { getCanonicalGasTokenAddress } from '@aztec/protocol-contracts/gas-token'; @@ -68,9 +68,15 @@ describe('benchmarks/tx_size_fees', () => { () => Promise.resolve(new PrivateFeePaymentMethod(token.address, fpc.address, aliceWallet)), ])('sends a tx with a fee', async createPaymentMethod => { const paymentMethod = await createPaymentMethod(); + const gasSettings = GasSettings.new({ + da: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, + l1: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, + l2: { gasLimit: 5, teardownGasLimit: 3, maxFeePerGas: Fr.ONE }, + inclusionFee: new Fr(6), + }); const tx = await token.methods .transfer(aliceWallet.getAddress(), bobAddress, 1n, 0) - .send({ fee: paymentMethod ? { gasSettings: GasSettings.empty(), paymentMethod } : undefined }) + .send({ fee: paymentMethod ? { gasSettings, paymentMethod } : undefined }) .wait(); expect(tx.status).toEqual(TxStatus.MINED); diff --git a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts index 3b0a8e20400..446330a461e 100644 --- a/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts +++ b/yarn-project/end-to-end/src/composed/cli_docs_sandbox.test.ts @@ -117,6 +117,7 @@ FPCContractArtifact GasTokenContractArtifact ImportTestContractArtifact InclusionProofsContractArtifact +KeyRegistryContractArtifact LendingContractArtifact MultiCallEntrypointContractArtifact ParentContractArtifact diff --git a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts index 3de9f8a1b0b..1a941a6f685 100644 --- a/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts +++ b/yarn-project/end-to-end/src/e2e_avm_simulator.test.ts @@ -80,15 +80,15 @@ describe('e2e_avm_simulator', () => { }, 50_000); it('Can execute ACVM function among AVM functions', async () => { - expect(await avmContract.methods.constant_field_acvm().simulate()).toEqual([123456n]); + expect(await avmContract.methods.constant_field_acvm().simulate()).toEqual(123456n); }); it('Can call AVM function from ACVM', async () => { - expect(await avmContract.methods.call_avm_from_acvm().simulate()).toEqual([123456n]); + expect(await avmContract.methods.call_avm_from_acvm().simulate()).toEqual(123456n); }); it('Can call ACVM function from AVM', async () => { - expect(await avmContract.methods.call_acvm_from_avm().simulate()).toEqual([123456n]); + expect(await avmContract.methods.call_acvm_from_avm().simulate()).toEqual(123456n); }); it('AVM sees settled nullifiers by ACVM', async () => { @@ -146,7 +146,7 @@ describe('e2e_avm_simulator', () => { describe('Storage', () => { it('Read immutable (initialized) storage (Field)', async () => { - expect(await avmContract.methods.read_storage_immutable().simulate()).toEqual([42n]); + expect(await avmContract.methods.read_storage_immutable().simulate()).toEqual(42n); }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts index e7d3b42101f..862c4a1ac09 100644 --- a/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_cross_chain_messaging.test.ts @@ -245,11 +245,16 @@ describe('e2e_cross_chain_messaging', () => { secretHashForL2MessageConsumption, ); + // get message leaf index, needed for claiming in public + const maybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + // 3. Consume L1 -> L2 message and try to mint publicly on L2 - should fail await expect( l2Bridge .withWallet(user2Wallet) - .methods.claim_public(ownerAddress, bridgeAmount, secretForL2MessageConsumption) + .methods.claim_public(ownerAddress, bridgeAmount, secretForL2MessageConsumption, messageLeafIndex) .prove(), ).rejects.toThrow(`No non-nullified L1 to L2 message found for message hash ${wrongMessage.hash().toString()}`); }, 120_000); diff --git a/yarn-project/end-to-end/src/e2e_delegate_calls.test.ts b/yarn-project/end-to-end/src/e2e_delegate_calls/delegate.test.ts similarity index 54% rename from yarn-project/end-to-end/src/e2e_delegate_calls.test.ts rename to yarn-project/end-to-end/src/e2e_delegate_calls/delegate.test.ts index 45fb4a22e1d..03246dcff0f 100644 --- a/yarn-project/end-to-end/src/e2e_delegate_calls.test.ts +++ b/yarn-project/end-to-end/src/e2e_delegate_calls/delegate.test.ts @@ -1,34 +1,25 @@ -import { type Wallet } from '@aztec/aztec.js'; -import { DelegatedOnContract, DelegatorContract } from '@aztec/noir-contracts.js'; - -import { setup } from './fixtures/utils.js'; +import { DelegateCallsTest } from './delegate_calls_test.js'; describe('e2e_delegate_calls', () => { - let wallet: Wallet; - let delegatorContract: DelegatorContract; - let delegatedOnContract: DelegatedOnContract; - let teardown: () => Promise; - - beforeEach(async () => { - ({ teardown, wallet } = await setup()); - }, 100_000); - - afterEach(() => teardown()); + const t = new DelegateCallsTest('delegate_calls'); + let { delegatorContract, delegatedOnContract, wallet } = t; + + beforeAll(async () => { + await t.applyBaseSnapshots(); + await t.setup(); + // Have to destructure again to ensure we have latest refs. + ({ delegatorContract, delegatedOnContract, wallet } = t); + }); - beforeEach(async () => { - delegatorContract = await DelegatorContract.deploy(wallet).send().deployed(); - delegatedOnContract = await DelegatedOnContract.deploy(wallet).send().deployed(); - }, 100_000); + afterAll(async () => { + await t.teardown(); + }); describe('delegates on another contract', () => { it("runs another contract's private function on delegator's storage", async () => { const sentValue = 42n; await delegatorContract.methods - .private_delegate_set_value( - delegatedOnContract.address, - delegatedOnContract.methods.private_set_value.selector, - [sentValue, wallet.getCompleteAddress().address], - ) + .private_delegate_set_value(delegatedOnContract.address, sentValue, wallet.getCompleteAddress().address) .send() .wait(); @@ -46,14 +37,7 @@ describe('e2e_delegate_calls', () => { it("runs another contract's enqueued public function on delegator's storage", async () => { const sentValue = 42n; - await delegatorContract.methods - .enqueued_delegate_set_value( - delegatedOnContract.address, - delegatedOnContract.methods.public_set_value.selector, - [sentValue], - ) - .send() - .wait(); + await delegatorContract.methods.enqueued_delegate_set_value(delegatedOnContract.address, sentValue).send().wait(); const delegatorValue = await delegatorContract.methods.view_public_value().simulate(); const delegatedOnValue = await delegatedOnContract.methods.view_public_value().simulate(); @@ -64,12 +48,7 @@ describe('e2e_delegate_calls', () => { it("runs another contract's public function on delegator's storage", async () => { const sentValue = 42n; - await delegatorContract.methods - .public_delegate_set_value(delegatedOnContract.address, delegatedOnContract.methods.public_set_value.selector, [ - sentValue, - ]) - .send() - .wait(); + await delegatorContract.methods.public_delegate_set_value(delegatedOnContract.address, sentValue).send().wait(); const delegatorValue = await delegatorContract.methods.view_public_value().simulate(); const delegatedOnValue = await delegatedOnContract.methods.view_public_value().simulate(); diff --git a/yarn-project/end-to-end/src/e2e_delegate_calls/delegate_calls_test.ts b/yarn-project/end-to-end/src/e2e_delegate_calls/delegate_calls_test.ts new file mode 100644 index 00000000000..457408a05f7 --- /dev/null +++ b/yarn-project/end-to-end/src/e2e_delegate_calls/delegate_calls_test.ts @@ -0,0 +1,72 @@ +import { getSchnorrAccount } from '@aztec/accounts/schnorr'; +import { type AccountWallet, type DebugLogger, createDebugLogger } from '@aztec/aztec.js'; +import { DelegatedOnContract, DelegatorContract } from '@aztec/noir-contracts.js'; + +import { SnapshotManager, type SubsystemsContext, addAccounts } from '../fixtures/snapshot_manager.js'; + +const { E2E_DATA_PATH: dataPath } = process.env; + +export class DelegateCallsTest { + private snapshotManager: SnapshotManager; + logger: DebugLogger; + wallet!: AccountWallet; + delegatorContract!: DelegatorContract; + delegatedOnContract!: DelegatedOnContract; + + constructor(testName: string) { + this.logger = createDebugLogger(`aztec:e2e_delegate_calls:${testName}`); + this.snapshotManager = new SnapshotManager(`e2e_delegate_calls/${testName}`, dataPath); + } + + /** + * Adds two state shifts to snapshot manager. + * 1. Add 3 accounts. + * 2. Publicly deploy accounts, deploy token contract and a "bad account". + */ + async applyBaseSnapshots() { + await this.snapshotManager.snapshot('accounts', addAccounts(1, this.logger), async ({ accountKeys }, { pxe }) => { + const accountManager = getSchnorrAccount(pxe, accountKeys[0][0], accountKeys[0][1], 1); + this.wallet = await accountManager.getWallet(); + this.logger.verbose(`Wallet address: ${this.wallet.getAddress()}`); + }); + + await this.snapshotManager.snapshot( + 'e2e_delegate_calls', + async () => { + this.logger.verbose(`Deploying DelegatorContract...`); + this.delegatorContract = await DelegatorContract.deploy(this.wallet).send().deployed(); + this.logger.verbose(`Delegator deployed to ${this.delegatorContract.address}`); + + this.logger.verbose(`Deploying DelegatedOnContract...`); + this.delegatedOnContract = await DelegatedOnContract.deploy(this.wallet).send().deployed(); + + return { + delegatorContractAddress: this.delegatorContract.address, + delegatedOnContractAddress: this.delegatedOnContract.address, + }; + }, + async ({ delegatorContractAddress, delegatedOnContractAddress }) => { + // Restore the token contract state. + this.delegatorContract = await DelegatorContract.at(delegatorContractAddress, this.wallet); + this.logger.verbose(`Delegator contract address: ${this.delegatorContract.address}`); + + this.delegatedOnContract = await DelegatedOnContract.at(delegatedOnContractAddress, this.wallet); + this.logger.verbose(`DelegatedOn address: ${this.delegatedOnContract.address}`); + }, + ); + } + + async setup() { + await this.snapshotManager.setup(); + } + + snapshot = ( + name: string, + apply: (context: SubsystemsContext) => Promise, + restore: (snapshotData: T, context: SubsystemsContext) => Promise = () => Promise.resolve(), + ): Promise => this.snapshotManager.snapshot(name, apply, restore); + + async teardown() { + await this.snapshotManager.teardown(); + } +} diff --git a/yarn-project/end-to-end/src/e2e_fees.test.ts b/yarn-project/end-to-end/src/e2e_fees.test.ts index a13b7830b90..d6301790f78 100644 --- a/yarn-project/end-to-end/src/e2e_fees.test.ts +++ b/yarn-project/end-to-end/src/e2e_fees.test.ts @@ -81,6 +81,7 @@ describe('e2e_fees', () => { sequencerAddress = wallets[2].getAddress(); gasBridgeTestHarness = await GasPortalTestingHarnessFactory.create({ + aztecNode: aztecNode, pxeService: pxe, publicClient: deployL1ContractsValues.publicClient, walletClient: deployL1ContractsValues.walletClient, diff --git a/yarn-project/end-to-end/src/e2e_key_registry.test.ts b/yarn-project/end-to-end/src/e2e_key_registry.test.ts new file mode 100644 index 00000000000..37f6ac8cea5 --- /dev/null +++ b/yarn-project/end-to-end/src/e2e_key_registry.test.ts @@ -0,0 +1,261 @@ +import { type AccountWallet, AztecAddress, Fr, type PXE } from '@aztec/aztec.js'; +import { GeneratorIndex } from '@aztec/circuits.js'; +import { poseidon2Hash } from '@aztec/foundation/crypto'; +import { KeyRegistryContract, TestContract } from '@aztec/noir-contracts.js'; + +import { jest } from '@jest/globals'; + +import { publicDeployAccounts, setup } from './fixtures/utils.js'; + +const TIMEOUT = 100_000; + +describe('SharedMutablePrivateGetter', () => { + let keyRegistry: KeyRegistryContract; + let testContract: TestContract; + let pxe: PXE; + jest.setTimeout(TIMEOUT); + + let wallets: AccountWallet[]; + + let teardown: () => Promise; + + beforeAll(async () => { + ({ teardown, pxe, wallets } = await setup(2)); + testContract = await TestContract.deploy(wallets[0]).send().deployed(); + keyRegistry = await KeyRegistryContract.deploy(wallets[0]).send().deployed(); + + await publicDeployAccounts(wallets[0], wallets.slice(0, 2)); + }, 120_000); + + const delay = async (blocks: number) => { + for (let i = 0; i < blocks; i++) { + await testContract.methods.delay().send().wait(); + } + }; + + afterAll(() => teardown()); + + describe('failure cases', () => { + let accountAddedToRegistry: AztecAddress; + + describe('should fail registering with bad input', () => { + const partialAddress = new Fr(69); + + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + // TODO(#5726): use computePublicKeysHash function + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? + accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + it('should fail registering with mismatched address', async () => { + const mismatchedAddress = Fr.random(); + + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(mismatchedAddress), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(), + ).rejects.toThrow('Computed address does not match supplied address'); + }); + + it('should fail registering with mismatched nullifier public key', async () => { + const mismatchedMasterNullifierPublicKey = Fr.random(); + + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + mismatchedMasterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(), + ).rejects.toThrow('Computed address does not match supplied address'); + }); + }); + + describe('should fail when rotating keys with bad input', () => { + it('should fail when trying to rotate setting a 0 key', async () => { + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), new Fr(0)) + .send() + .wait(), + ).rejects.toThrow('New nullifier public key must be non-zero'); + }); + + it('should fail when trying to rotate for another address without authwit', async () => { + await expect( + keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[1].getAddress(), new Fr(2)) + .send() + .wait(), + ).rejects.toThrow('Assertion failed: Message not authorized by account'); + }); + }); + }); + + describe('key registration flow', () => { + let accountAddedToRegistry: AztecAddress; + + it('should generate and register with original keys', async () => { + const partialAddress = new Fr(69); + + const masterNullifierPublicKey = new Fr(12); + const masterIncomingViewingPublicKey = new Fr(34); + const masterOutgoingViewingPublicKey = new Fr(56); + const masterTaggingPublicKey = new Fr(78); + + const publicKeysHash = poseidon2Hash([ + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + GeneratorIndex.PUBLIC_KEYS_HASH, + ]); + + // We hash the partial address and the public keys hash to get the account address + // TODO(#5726): Move the following line to AztecAddress class? + accountAddedToRegistry = poseidon2Hash([partialAddress, publicKeysHash, GeneratorIndex.CONTRACT_ADDRESS_V1]); + + await keyRegistry + .withWallet(wallets[0]) + .methods.register( + AztecAddress.fromField(accountAddedToRegistry), + partialAddress, + masterNullifierPublicKey, + masterIncomingViewingPublicKey, + masterOutgoingViewingPublicKey, + masterTaggingPublicKey, + ) + .send() + .wait(); + }); + + it('checks our registry contract from test contract and fails because the address has not been registered yet', async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(Fr.ZERO); + }); + + it('checks our registry contract from test contract and finds the address and associated nullifier public key after a delay', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, accountAddedToRegistry) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(12)); + }); + }); + + describe('key rotation flow', () => { + it('we rotate the nullifier key', async () => { + // This changes + const newMasterNullifierPublicKey = new Fr(910); + + await keyRegistry + .withWallet(wallets[0]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey) + .send() + .wait(); + }); + + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + }); + + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + }); + }); + + describe('key rotation flow with authwit', () => { + it('wallet 0 lets wallet 1 call rotate_nullifier_public_key on his behalf with a pre-defined new public key', async () => { + // This changes + const newMasterNullifierPublicKey = new Fr(420); + + const action = keyRegistry + .withWallet(wallets[1]) + .methods.rotate_nullifier_public_key(wallets[0].getAddress(), newMasterNullifierPublicKey); + + await wallets[0] + .setPublicAuthWit({ caller: wallets[1].getCompleteAddress().address, action }, true) + .send() + .wait(); + + await action.send().wait(); + }); + + it("checks our registry contract from test contract and finds our old public key because the key rotation hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(910)); + }); + + it('checks our registry contract from test contract and finds the new nullifier public key that has been rotated', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter_for_registry_contract(keyRegistry.address, 1, wallets[0].getAddress()) + .send() + .wait(); + + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(420)); + }); + }); +}); diff --git a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts index 102e10069d3..0310b4bbfd1 100644 --- a/yarn-project/end-to-end/src/e2e_nested_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_nested_contract.test.ts @@ -169,7 +169,7 @@ describe('e2e_nested_contract', () => { it('calls a method with multiple arguments', async () => { logger.info(`Calling main on importer contract`); - await importerContract.methods.main(testContract.address).send().wait(); + await importerContract.methods.main_contract(testContract.address).send().wait(); }, 30_000); it('calls a method no arguments', async () => { diff --git a/yarn-project/end-to-end/src/e2e_note_getter.test.ts b/yarn-project/end-to-end/src/e2e_note_getter.test.ts index 27e6be2c03a..54a2084be58 100644 --- a/yarn-project/end-to-end/src/e2e_note_getter.test.ts +++ b/yarn-project/end-to-end/src/e2e_note_getter.test.ts @@ -41,10 +41,11 @@ describe('e2e_note_getter', () => { // await Promise.all(numbers.map(number => contract.methods.insert_note(number).send().wait())); // It causes a race condition complaining about root mismatch - await contract.methods - .insert_notes([...Array(10).keys()]) - .send() - .wait(); + // Note: Separated the below into calls of 3 to avoid reaching logs per call limit + await contract.methods.insert_notes([0, 1, 2]).send().wait(); + await contract.methods.insert_notes([3, 4, 5]).send().wait(); + await contract.methods.insert_notes([6, 7, 8]).send().wait(); + await contract.methods.insert_note(9, new Fr(1n)).send().wait(); await contract.methods.insert_note(5, Fr.ZERO).send().wait(); const [returnEq, returnNeq, returnLt, returnGt, returnLte, returnGte] = await Promise.all([ diff --git a/yarn-project/end-to-end/src/e2e_ordering.test.ts b/yarn-project/end-to-end/src/e2e_ordering.test.ts index e05f09b1d21..16ce4309f7d 100644 --- a/yarn-project/end-to-end/src/e2e_ordering.test.ts +++ b/yarn-project/end-to-end/src/e2e_ordering.test.ts @@ -109,16 +109,19 @@ describe('e2e_ordering', () => { // Emitting logs twice (first in a nested call, then directly) leads // to a misordering of them by the public kernel because it sees them // in reverse order. More info in this thread: https://discourse.aztec.network/t/identifying-the-ordering-of-state-access-across-contract-calls/382/12#transition-counters-for-private-calls-2 - // Once fixed, re-include the `set_value_twice_with_nested_first` test - //it.each(['set_value_twice_with_nested_first', 'set_value_twice_with_nested_last'] as const)( - it.each(['set_value_twice_with_nested_last'] as const)('orders unencrypted logs in %s', async method => { - const expectedOrder = expectedOrders[method]; + // The below only works due to a hack which sorts the logs in ts + // See tail_phase_manager.ts + it.each(['set_value_twice_with_nested_first', 'set_value_twice_with_nested_last'] as const)( + 'orders unencrypted logs in %s', + async method => { + const expectedOrder = expectedOrders[method]; - await child.methods[method]().send().wait(); + await child.methods[method]().send().wait(); - // Logs are emitted in the expected order - await expectLogsFromLastBlockToBe(expectedOrder); - }); + // Logs are emitted in the expected order + await expectLogsFromLastBlockToBe(expectedOrder); + }, + ); }); }); }); diff --git a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts index b26721bd672..e8aa0bacee3 100644 --- a/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_cross_chain_messaging.test.ts @@ -5,6 +5,8 @@ import { type DebugLogger, type DeployL1Contracts, EthAddress, + type EthAddressLike, + type FieldLike, Fr, L1Actor, L1ToL2Message, @@ -92,8 +94,13 @@ describe('e2e_public_cross_chain_messaging', () => { // Wait for the message to be available for consumption await crossChainTestHarness.makeMessageConsumable(msgHash); + // Get message leaf index, needed for claiming in public + const maybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + // 3. Consume L1 -> L2 message and mint public tokens on L2 - await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, secret); + await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, secret, messageLeafIndex); await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount); const afterBalance = bridgeAmount; @@ -161,14 +168,26 @@ describe('e2e_public_cross_chain_messaging', () => { secretHash, ); + // get message leaf index, needed for claiming in public + const maybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + // user2 tries to consume this message and minting to itself -> should fail since the message is intended to be consumed only by owner. await expect( - l2Bridge.withWallet(user2Wallet).methods.claim_public(user2Wallet.getAddress(), bridgeAmount, secret).prove(), + l2Bridge + .withWallet(user2Wallet) + .methods.claim_public(user2Wallet.getAddress(), bridgeAmount, secret, messageLeafIndex) + .prove(), ).rejects.toThrow(`No non-nullified L1 to L2 message found for message hash ${wrongMessage.hash().toString()}`); // user2 consumes owner's L1-> L2 message on bridge contract and mints public tokens on L2 logger.info("user2 consumes owner's message on L2 Publicly"); - await l2Bridge.withWallet(user2Wallet).methods.claim_public(ownerAddress, bridgeAmount, secret).send().wait(); + await l2Bridge + .withWallet(user2Wallet) + .methods.claim_public(ownerAddress, bridgeAmount, secret, messageLeafIndex) + .send() + .wait(); // ensure funds are gone to owner and not user2. await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount); await crossChainTestHarness.expectPublicBalanceOnL2(user2Wallet.getAddress(), 0n); @@ -312,7 +331,8 @@ describe('e2e_public_cross_chain_messaging', () => { const testContract = await TestContract.deploy(user1Wallet).send().deployed(); const consumeMethod = isPrivate - ? testContract.methods.consume_message_from_arbitrary_sender_private + ? (content: FieldLike, secret: FieldLike, sender: EthAddressLike, _leafIndex: FieldLike) => + testContract.methods.consume_message_from_arbitrary_sender_private(content, secret, sender) : testContract.methods.consume_message_from_arbitrary_sender_public; const secret = Fr.random(); @@ -329,7 +349,7 @@ describe('e2e_public_cross_chain_messaging', () => { const [message1Index, _1] = (await aztecNode.getL1ToL2MessageMembershipWitness('latest', message.hash(), 0n))!; // Finally, we consume the L1 -> L2 message using the test contract either from private or public - await consumeMethod(message.content, secret, message.sender.sender).send().wait(); + await consumeMethod(message.content, secret, message.sender.sender, message1Index).send().wait(); // We send and consume the exact same message the second time to test that oracles correctly return the new // non-nullified message @@ -348,7 +368,7 @@ describe('e2e_public_cross_chain_messaging', () => { // Now we consume the message again. Everything should pass because oracle should return the duplicate message // which is not nullified - await consumeMethod(message.content, secret, message.sender.sender).send().wait(); + await consumeMethod(message.content, secret, message.sender.sender, message2Index).send().wait(); }, 120_000, ); diff --git a/yarn-project/end-to-end/src/e2e_public_to_private_messaging.test.ts b/yarn-project/end-to-end/src/e2e_public_to_private_messaging.test.ts index 805628e74a8..51077dc9de8 100644 --- a/yarn-project/end-to-end/src/e2e_public_to_private_messaging.test.ts +++ b/yarn-project/end-to-end/src/e2e_public_to_private_messaging.test.ts @@ -1,4 +1,4 @@ -import { type AztecAddress, type DebugLogger, type EthAddress } from '@aztec/aztec.js'; +import { type AztecAddress, type AztecNode, type DebugLogger, type EthAddress } from '@aztec/aztec.js'; import { setup } from './fixtures/utils.js'; import { CrossChainTestHarness } from './shared/cross_chain_test_harness.js'; @@ -7,18 +7,23 @@ describe('e2e_public_to_private_messaging', () => { let logger: DebugLogger; let teardown: () => Promise; + let aztecNode: AztecNode; let ethAccount: EthAddress; - let underlyingERC20: any; - let ownerAddress: AztecAddress; - let crossChainTestHarness: CrossChainTestHarness; beforeEach(async () => { - const { aztecNode, pxe, deployL1ContractsValues, wallet, logger: logger_, teardown: teardown_ } = await setup(2); + const { + aztecNode: aztecNode_, + pxe, + deployL1ContractsValues, + wallet, + logger: logger_, + teardown: teardown_, + } = await setup(2); crossChainTestHarness = await CrossChainTestHarness.new( - aztecNode, + aztecNode_, pxe, deployL1ContractsValues.publicClient, deployL1ContractsValues.walletClient, @@ -26,6 +31,7 @@ describe('e2e_public_to_private_messaging', () => { logger_, ); + aztecNode = crossChainTestHarness.aztecNode; ethAccount = crossChainTestHarness.ethAccount; ownerAddress = crossChainTestHarness.ownerAddress; underlyingERC20 = crossChainTestHarness.underlyingERC20; @@ -53,7 +59,12 @@ describe('e2e_public_to_private_messaging', () => { await crossChainTestHarness.makeMessageConsumable(msgHash); - await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, secret); + // get message leaf index, needed for claiming in public + const maybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + + await crossChainTestHarness.consumeMessageOnAztecAndMintPublicly(bridgeAmount, secret, messageLeafIndex); await crossChainTestHarness.expectPublicBalanceOnL2(ownerAddress, bridgeAmount); // Create the commitment to be spent in the private domain diff --git a/yarn-project/end-to-end/src/e2e_state_vars.test.ts b/yarn-project/end-to-end/src/e2e_state_vars.test.ts index 56783ceee2e..8a6ed6dc23e 100644 --- a/yarn-project/end-to-end/src/e2e_state_vars.test.ts +++ b/yarn-project/end-to-end/src/e2e_state_vars.test.ts @@ -1,5 +1,5 @@ -import { type Wallet } from '@aztec/aztec.js'; -import { DocsExampleContract } from '@aztec/noir-contracts.js'; +import { AztecAddress, Fr, type PXE, type Wallet } from '@aztec/aztec.js'; +import { AuthContract, DocsExampleContract, TestContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; @@ -8,6 +8,7 @@ import { setup } from './fixtures/utils.js'; const TIMEOUT = 100_000; describe('e2e_state_vars', () => { + let pxe: PXE; jest.setTimeout(TIMEOUT); let wallet: Wallet; @@ -19,7 +20,7 @@ describe('e2e_state_vars', () => { const RANDOMNESS = 2n; beforeAll(async () => { - ({ teardown, wallet } = await setup()); + ({ teardown, wallet, pxe } = await setup(2)); contract = await DocsExampleContract.deploy(wallet).send().deployed(); }, 30_000); @@ -38,6 +39,7 @@ describe('e2e_state_vars', () => { // checking the return values with: // 1. A constrained private function that reads it directly // 2. A constrained private function that calls another private function that reads. + // The indirect, adds 1 to the point to ensure that we are returning the correct value. await contract.methods.initialize_shared_immutable(1).send().wait(); @@ -45,12 +47,8 @@ describe('e2e_state_vars', () => { const b = await contract.methods.get_shared_immutable_constrained_private_indirect().simulate(); const c = await contract.methods.get_shared_immutable().simulate(); - expect((a as any)[0]).toEqual((c as any)['account'].toBigInt()); - expect((a as any)[1]).toEqual((c as any)['points']); - expect((b as any)[0]).toEqual((c as any)['account'].toBigInt()); - expect((b as any)[1]).toEqual((c as any)['points']); - - expect(a).toEqual(b); + expect(a).toEqual(c); + expect(b).toEqual({ account: c.account, points: c.points + 1n }); await contract.methods.match_shared_immutable(c.account, c.points).send().wait(); }); @@ -58,20 +56,28 @@ describe('e2e_state_vars', () => { // Reads the value using an unconstrained function checking the return values with: // 1. A constrained public function that reads it directly // 2. A constrained public function that calls another public function that reads. + // The indirect, adds 1 to the point to ensure that we are returning the correct value. const a = await contract.methods.get_shared_immutable_constrained_public().simulate(); const b = await contract.methods.get_shared_immutable_constrained_public_indirect().simulate(); const c = await contract.methods.get_shared_immutable().simulate(); - expect((a as any)[0]).toEqual((c as any)['account'].toBigInt()); - expect((a as any)[1]).toEqual((c as any)['points']); - expect((b as any)[0]).toEqual((c as any)['account'].toBigInt()); - expect((b as any)[1]).toEqual((c as any)['points']); + expect(a).toEqual(c); + expect(b).toEqual({ account: c.account, points: c.points + 1n }); - expect(a).toEqual(b); await contract.methods.match_shared_immutable(c.account, c.points).send().wait(); }); + it('public multiread of SharedImmutable', async () => { + // Reads the value using an unconstrained function checking the return values with: + // 1. A constrained public function that reads 5 times directly (going beyond the previous 4 Field return value) + + const a = await contract.methods.get_shared_immutable_constrained_public_multiple().simulate(); + const c = await contract.methods.get_shared_immutable().simulate(); + + expect(a).toEqual([c, c, c, c, c]); + }); + it('initializing SharedImmutable the second time should fail', async () => { // Jest executes the tests sequentially and the first call to initialize_shared_immutable was executed // in the previous test, so the call bellow should fail. @@ -217,4 +223,53 @@ describe('e2e_state_vars', () => { expect(randomness).toEqual(RANDOMNESS); }); }); + + describe('SharedMutablePrivateGetter', () => { + let authContract: AuthContract; + let testContract: TestContract; + + const delay = async (blocks: number) => { + for (let i = 0; i < blocks; i++) { + await authContract.methods.get_authorized().send().wait(); + } + }; + + beforeAll(async () => { + testContract = await TestContract.deploy(wallet).send().deployed(); + // We use the auth contract here because has a nice, clear, simple implementation of the Shared Mutable, + // and we will need to read from it to test our private getter. + authContract = await AuthContract.deploy(wallet, wallet.getAddress()).send().deployed(); + + // We set the authorized value here, knowing there will be some delay before the value change takes place + await authContract + .withWallet(wallet) + .methods.set_authorized(AztecAddress.fromField(new Fr(6969696969))) + .send() + .wait(); + }, 30_000); + + it("checks authorized in auth contract from test contract and finds the old value because the change hasn't been applied yet", async () => { + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter(authContract.address, 2) + .send() + .wait(); + + // The function above emits an unencrypted log as a means of returning the data + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(0)); + }); + + it('checks authorized in auth contract from test contract and finds the correctly set value', async () => { + await delay(5); + + const { txHash } = await testContract.methods + .test_shared_mutable_private_getter(authContract.address, 2) + .send() + .wait(); + + // The function above emits an unencrypted log as a means of returning the data + const rawLogs = await pxe.getUnencryptedLogs({ txHash }); + expect(Fr.fromBuffer(rawLogs.logs[0].log.data)).toEqual(new Fr(6969696969)); + }); + }); }); diff --git a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts index 1cb3ab1ba33..9f0d16ed810 100644 --- a/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts +++ b/yarn-project/end-to-end/src/flakey_e2e_account_init_fees.test.ts @@ -94,6 +94,7 @@ describe('e2e_fees_account_init', () => { }); gasBridgeTestHarness = await GasPortalTestingHarnessFactory.create({ + aztecNode: ctx.aztecNode, pxeService: ctx.pxe, publicClient: ctx.deployL1ContractsValues.publicClient, walletClient: ctx.deployL1ContractsValues.walletClient, diff --git a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts index 342e0ce917f..63975935c91 100644 --- a/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/cross_chain_test_harness.ts @@ -319,10 +319,10 @@ export class CrossChainTestHarness { await this.addPendingShieldNoteToPXE(bridgeAmount, secretHashForRedeemingMintedNotes, consumptionReceipt.txHash); } - async consumeMessageOnAztecAndMintPublicly(bridgeAmount: bigint, secret: Fr) { + async consumeMessageOnAztecAndMintPublicly(bridgeAmount: bigint, secret: Fr, leafIndex: bigint) { this.logger.info('Consuming messages on L2 Publicly'); // Call the mint tokens function on the Aztec.nr contract - await this.l2Bridge.methods.claim_public(this.ownerAddress, bridgeAmount, secret).send().wait(); + await this.l2Bridge.methods.claim_public(this.ownerAddress, bridgeAmount, secret, leafIndex).send().wait(); } async withdrawPrivateFromAztecToL1(withdrawAmount: bigint, nonce: Fr = Fr.ZERO): Promise> { diff --git a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts index 1897042ab05..7a0c7625302 100644 --- a/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts +++ b/yarn-project/end-to-end/src/shared/gas_portal_test_harness.ts @@ -1,5 +1,6 @@ import { type AztecAddress, + type AztecNode, type DebugLogger, EthAddress, Fr, @@ -27,6 +28,7 @@ export interface IGasBridgingTestHarness { } export interface GasPortalTestingHarnessFactoryConfig { + aztecNode: AztecNode; pxeService: PXE; publicClient: PublicClient; walletClient: WalletClient; @@ -34,6 +36,7 @@ export interface GasPortalTestingHarnessFactoryConfig { logger: DebugLogger; mockL1?: boolean; } + export class GasPortalTestingHarnessFactory { private constructor(private config: GasPortalTestingHarnessFactoryConfig) {} @@ -49,7 +52,7 @@ export class GasPortalTestingHarnessFactory { } private async createReal() { - const { pxeService, publicClient, walletClient, wallet, logger } = this.config; + const { aztecNode, pxeService, publicClient, walletClient, wallet, logger } = this.config; const ethAccount = EthAddress.fromString((await walletClient.getAddresses())[0]); const l1ContractAddresses = (await pxeService.getNodeInfo()).l1ContractAddresses; @@ -82,6 +85,7 @@ export class GasPortalTestingHarnessFactory { const gasL2 = await GasTokenContract.at(getCanonicalGasTokenAddress(gasPortalAddress), wallet); return new GasBridgingTestHarness( + aztecNode, pxeService, logger, gasL2, @@ -118,6 +122,8 @@ class MockGasBridgingTestHarness implements IGasBridgingTestHarness { */ class GasBridgingTestHarness implements IGasBridgingTestHarness { constructor( + /** Aztec node */ + public aztecNode: AztecNode, /** Private eXecution Environment (PXE). */ public pxeService: PXE, /** Logger. */ @@ -201,10 +207,10 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { return Fr.fromString(messageHash); } - async consumeMessageOnAztecAndMintPublicly(bridgeAmount: bigint, owner: AztecAddress, secret: Fr) { + async consumeMessageOnAztecAndMintPublicly(bridgeAmount: bigint, owner: AztecAddress, secret: Fr, leafIndex: bigint) { this.logger.info('Consuming messages on L2 Publicly'); // Call the mint tokens function on the Aztec.nr contract - await this.l2Token.methods.claim_public(owner, bridgeAmount, secret).send().wait(); + await this.l2Token.methods.claim_public(owner, bridgeAmount, secret, leafIndex).send().wait(); } async getL2PublicBalanceOf(owner: AztecAddress) { @@ -223,15 +229,20 @@ class GasBridgingTestHarness implements IGasBridgingTestHarness { await this.mintTokensOnL1(l1TokenBalance); // 2. Deposit tokens to the TokenPortal - await this.sendTokensToPortalPublic(bridgeAmount, owner, secretHash); + const msgHash = await this.sendTokensToPortalPublic(bridgeAmount, owner, secretHash); expect(await this.getL1BalanceOf(this.ethAccount)).toBe(l1TokenBalance - bridgeAmount); // Perform an unrelated transactions on L2 to progress the rollup by 2 blocks. await this.l2Token.methods.check_balance(0).send().wait(); await this.l2Token.methods.check_balance(0).send().wait(); + // Get message leaf index, needed for claiming in public + const maybeIndexAndPath = await this.aztecNode.getL1ToL2MessageMembershipWitness('latest', msgHash, 0n); + expect(maybeIndexAndPath).toBeDefined(); + const messageLeafIndex = maybeIndexAndPath![0]; + // 3. Consume L1-> L2 message and mint public tokens on L2 - await this.consumeMessageOnAztecAndMintPublicly(bridgeAmount, owner, secret); + await this.consumeMessageOnAztecAndMintPublicly(bridgeAmount, owner, secret, messageLeafIndex); await this.expectPublicBalanceOnL2(owner, bridgeAmount); } } diff --git a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts index 81dc6b3cb4c..f23c35ea442 100644 --- a/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts +++ b/yarn-project/end-to-end/src/shared/uniswap_l1_l2.ts @@ -14,6 +14,7 @@ import { InboxAbi, UniswapPortalAbi, UniswapPortalBytecode } from '@aztec/l1-art import { UniswapContract } from '@aztec/noir-contracts.js/Uniswap'; import { jest } from '@jest/globals'; +import { strict as assert } from 'assert'; import { type Account, type Chain, @@ -409,9 +410,22 @@ export const uniswapL1L2TestSuite = ( // Wait for the message to be available for consumption await wethCrossChainHarness.makeMessageConsumable(wethDepositMsgHash); + // Get message leaf index, needed for claiming in public + const wethDepositMaybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness( + 'latest', + wethDepositMsgHash, + 0n, + ); + assert(wethDepositMaybeIndexAndPath !== undefined, 'Message not found in tree'); + const wethDepositMessageLeafIndex = wethDepositMaybeIndexAndPath[0]; + // 2. Claim WETH on L2 logger.info('Minting weth on L2'); - await wethCrossChainHarness.consumeMessageOnAztecAndMintPublicly(wethAmountToBridge, secretForMintingWeth); + await wethCrossChainHarness.consumeMessageOnAztecAndMintPublicly( + wethAmountToBridge, + secretForMintingWeth, + wethDepositMessageLeafIndex, + ); await wethCrossChainHarness.expectPublicBalanceOnL2(ownerAddress, wethAmountToBridge); // Store balances @@ -585,9 +599,22 @@ export const uniswapL1L2TestSuite = ( // Wait for the message to be available for consumption await daiCrossChainHarness.makeMessageConsumable(outTokenDepositMsgHash); + // Get message leaf index, needed for claiming in public + const outTokenDepositMaybeIndexAndPath = await aztecNode.getL1ToL2MessageMembershipWitness( + 'latest', + outTokenDepositMsgHash, + 0n, + ); + assert(outTokenDepositMaybeIndexAndPath !== undefined, 'Message not found in tree'); + const outTokenDepositMessageLeafIndex = outTokenDepositMaybeIndexAndPath[0]; + // 6. claim dai on L2 logger.info('Consuming messages to mint dai on L2'); - await daiCrossChainHarness.consumeMessageOnAztecAndMintPublicly(daiAmountToBridge, secretForDepositingSwappedDai); + await daiCrossChainHarness.consumeMessageOnAztecAndMintPublicly( + daiAmountToBridge, + secretForDepositingSwappedDai, + outTokenDepositMessageLeafIndex, + ); await daiCrossChainHarness.expectPublicBalanceOnL2(ownerAddress, daiL2BalanceBeforeSwap + daiAmountToBridge); const wethL2BalanceAfterSwap = await wethCrossChainHarness.getL2PublicBalanceOf(ownerAddress); diff --git a/yarn-project/foundation/src/abi/abi.ts b/yarn-project/foundation/src/abi/abi.ts index 1a9fb2b8901..9f2d48800f8 100644 --- a/yarn-project/foundation/src/abi/abi.ts +++ b/yarn-project/foundation/src/abi/abi.ts @@ -240,6 +240,16 @@ export interface DebugInfo { locations: Record; } +/** + * The debug information for a given program (a collection of functions) + */ +export interface ProgramDebugInfo { + /** + * A list of debug information that matches with each function in a program + */ + debug_infos: Array; +} + /** * Maps a file ID to its metadata for debugging purposes. */ @@ -355,10 +365,13 @@ export function getFunctionDebugMetadata( functionArtifact: FunctionArtifact, ): FunctionDebugMetadata | undefined { if (functionArtifact.debugSymbols && contractArtifact.fileMap) { - const debugSymbols = JSON.parse( + const programDebugSymbols = JSON.parse( inflate(Buffer.from(functionArtifact.debugSymbols, 'base64'), { to: 'string', raw: true }), ); - return { debugSymbols, files: contractArtifact.fileMap }; + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/5813) + // We only support handling debug info for the contract function entry point. + // So for now we simply index into the first debug info. + return { debugSymbols: programDebugSymbols.debug_infos[0], files: contractArtifact.fileMap }; } return undefined; } diff --git a/yarn-project/foundation/src/abi/decoder.ts b/yarn-project/foundation/src/abi/decoder.ts index deafe602ae1..c98bac63823 100644 --- a/yarn-project/foundation/src/abi/decoder.ts +++ b/yarn-project/foundation/src/abi/decoder.ts @@ -1,20 +1,19 @@ import { AztecAddress } from '../aztec-address/index.js'; import { type Fr } from '../fields/index.js'; -import { type ABIParameter, type ABIVariable, type AbiType, type FunctionArtifact } from './abi.js'; +import { type ABIParameter, type ABIVariable, type AbiType, type FunctionAbi } from './abi.js'; import { isAztecAddressStruct } from './utils.js'; /** * The type of our decoded ABI. */ export type DecodedReturn = bigint | boolean | AztecAddress | DecodedReturn[] | { [key: string]: DecodedReturn }; -export type ProcessReturnValues = (DecodedReturn | undefined)[] | undefined; /** * Decodes return values from a function call. * Missing support for integer and string. */ class ReturnValuesDecoder { - constructor(private artifact: FunctionArtifact, private flattened: Fr[]) {} + constructor(private artifact: FunctionAbi, private flattened: Fr[]) {} /** * Decodes a single return value from field to the given type. @@ -97,7 +96,7 @@ class ReturnValuesDecoder { * @param returnValues - The decoded return values. * @returns */ -export function decodeReturnValues(abi: FunctionArtifact, returnValues: Fr[]) { +export function decodeReturnValues(abi: FunctionAbi, returnValues: Fr[]) { return new ReturnValuesDecoder(abi, returnValues.slice()).decode(); } diff --git a/yarn-project/kv-store/package.json b/yarn-project/kv-store/package.json index d5bfb66aec4..d22d0190c7d 100644 --- a/yarn-project/kv-store/package.json +++ b/yarn-project/kv-store/package.json @@ -37,7 +37,7 @@ }, "dependencies": { "@aztec/foundation": "workspace:^", - "lmdb": "^2.9.2" + "lmdb": "^3.0.6" }, "devDependencies": { "@jest/globals": "^29.5.0", diff --git a/yarn-project/noir-compiler/package.json b/yarn-project/noir-compiler/package.json index 110a881ff8f..c35f9e851d5 100644 --- a/yarn-project/noir-compiler/package.json +++ b/yarn-project/noir-compiler/package.json @@ -58,6 +58,7 @@ "fs-extra": "^11.1.1", "lodash.camelcase": "^4.3.0", "lodash.capitalize": "^4.2.1", + "lodash.uniqby": "^4.7.0", "memfs": "^4.6.0", "pako": "^2.1.0", "semver": "^7.5.4", @@ -70,6 +71,7 @@ "@types/jest": "^29.5.0", "@types/lodash.camelcase": "^4.3.7", "@types/lodash.capitalize": "^4.2.7", + "@types/lodash.uniqby": "^4.7.9", "@types/node": "^18.7.23", "@types/pako": "^2.0.0", "@types/semver": "^7.5.4", diff --git a/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts b/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts index 02fa9eb6c0b..a3330b8368f 100644 --- a/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts +++ b/yarn-project/noir-compiler/src/cli/add_noir_compiler_commander_actions.ts @@ -12,15 +12,10 @@ export function addCodegenCommanderAction(program: Command, _: LogFn = () => {}) .command('codegen') .argument('', 'Path to the Noir ABI or project dir.') .option('-o, --outdir ', 'Output folder for the generated code.') - .option('--ts', 'Generate TypeScript wrapper.') - .option('--nr', 'Generate Noir interface.') .option('--force', 'Force code generation even when the contract has not changed.') .description('Validates and generates an Aztec Contract ABI from Noir ABI.') - .action(async (noirAbiPath: string, { outdir, ts, nr, force }) => { - if (ts && nr) { - throw new Error('--ts and --nr are mutually exclusive.'); - } + .action(async (noirAbiPath: string, { outdir, force }) => { const { generateCode } = await import('./codegen.js'); - generateCode(outdir || dirname(noirAbiPath), noirAbiPath, { ts, nr, force }); + generateCode(outdir || dirname(noirAbiPath), noirAbiPath, { force }); }); } diff --git a/yarn-project/noir-compiler/src/cli/codegen.ts b/yarn-project/noir-compiler/src/cli/codegen.ts index 47aaeaa390b..858109a982b 100644 --- a/yarn-project/noir-compiler/src/cli/codegen.ts +++ b/yarn-project/noir-compiler/src/cli/codegen.ts @@ -5,14 +5,13 @@ import crypto from 'crypto'; import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'fs'; import path from 'path'; -import { generateNoirContractInterface } from '../contract-interface-gen/noir.js'; import { generateTypescriptContractInterface } from '../contract-interface-gen/typescript.js'; const cacheFilePath = './codegenCache.json'; let cache: Record = {}; /** Generate code options */ -type GenerateCodeOptions = { /** Typescript */ ts?: boolean; /** Noir */ nr?: boolean; force?: boolean }; +type GenerateCodeOptions = { force?: boolean }; /** * Generates Noir interface or Typescript interface for a folder or single file from a Noir compilation artifact. @@ -49,26 +48,18 @@ function generateFromNoirAbi(outputPath: string, noirAbiPath: string, opts: Gene const contract = JSON.parse(readFileSync(noirAbiPath, 'utf8')); const aztecAbi = loadContractArtifact(contract); - const { nr, ts } = opts; mkdirSync(outputPath, { recursive: true }); - if (nr) { - const noirContract = generateNoirContractInterface(aztecAbi); - writeFileSync(`${outputPath}/${aztecAbi.name}.nr`, noirContract); - return; + let relativeArtifactPath = path.relative(outputPath, noirAbiPath); + if (relativeArtifactPath === path.basename(noirAbiPath)) { + // Prepend ./ for local import if the folder is the same + relativeArtifactPath = `./${relativeArtifactPath}`; } - if (ts) { - let relativeArtifactPath = path.relative(outputPath, noirAbiPath); - if (relativeArtifactPath === path.basename(noirAbiPath)) { - // Prepend ./ for local import if the folder is the same - relativeArtifactPath = `./${relativeArtifactPath}`; - } + const tsWrapper = generateTypescriptContractInterface(aztecAbi, relativeArtifactPath); + writeFileSync(`${outputPath}/${aztecAbi.name}.ts`, tsWrapper); - const tsWrapper = generateTypescriptContractInterface(aztecAbi, relativeArtifactPath); - writeFileSync(`${outputPath}/${aztecAbi.name}.ts`, tsWrapper); - } updateCache(contractName, currentHash); } diff --git a/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts b/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts deleted file mode 100644 index 52fd0788973..00000000000 --- a/yarn-project/noir-compiler/src/contract-interface-gen/noir.ts +++ /dev/null @@ -1,308 +0,0 @@ -import { - type ABIParameter, - type ABIVariable, - type ContractArtifact, - type FunctionArtifact, - FunctionSelector, - FunctionType, - type StructType, -} from '@aztec/foundation/abi'; -import { times } from '@aztec/foundation/collection'; - -import camelCase from 'lodash.camelcase'; -import capitalize from 'lodash.capitalize'; - -/** - * Returns whether this function type corresponds to a private call. - * @param functionType - The function type. - * @returns Whether this function type corresponds to a private call. - */ -function isPrivateCall(functionType: FunctionType) { - return functionType === FunctionType.SECRET; -} - -/** - * Generates a call to a private function using the context. - * @param selector - The selector of a function. - * @param functionType - Type of the function. - * @returns A code string. - */ -function generateCallStatement( - selector: FunctionSelector, - functionType: FunctionType, - callingContext: 'private' | 'public', -) { - const callMethod = isPrivateCall(functionType) ? 'call_private_function' : 'call_public_function'; - const args = [ - 'self.address', - `FunctionSelector::from_field(${selector.toString()})`, - 'serialized_args', - ...(callingContext === 'private' ? [] : ['GasOpts::default()']), - ]; - return ` - context.${callMethod}(${args.join(', ')})`; -} - -/** - * Formats a string as pascal case. - * @param str - A string. - * @returns A capitalized camelcase string. - */ -function toPascalCase(str: string) { - const camel = camelCase(str); - return camel[0].toUpperCase() + camel.slice(1); -} - -/** - * Returns a struct name given a list of fragments. - * @param fragments - Fragments. - * @returns The concatenation of the capitalized fragments. - */ -function getStructName(...fragments: string[]) { - return fragments.map(toPascalCase).join('') + 'Struct'; -} - -/** - * Returns a Noir type name for the given ABI variable. - * @param param - ABI variable to translate to a Noir type name. - * @param parentNames - Function name or parent structs or arrays to use for struct qualified names. - * @returns A valid Noir basic type name or a name for a struct. - */ -function getTypeName(param: ABIVariable, ...parentNames: string[]): string { - const type = param.type; - switch (type.kind) { - case 'field': - return 'Field'; - case 'boolean': - return 'bool'; - case 'integer': - return `${type.sign === 'signed' ? 'i' : 'u'}${type.width}`; - case 'string': - throw new Error(`Strings not supported yet`); - case 'array': - return `[${getTypeName({ name: param.name, type: type.type }, ...parentNames)};${type.length}]`; - case 'struct': - return getStructName(param.name, ...parentNames); - default: - throw new Error(`Unknown type ${type}`); - } -} - -/** - * Generates a parameter string. - * @param param - ABI parameter. - * @param functionData - Parent function. - * @returns A Noir string with the param name and type to be used in a function call. - */ -function generateParameter(param: ABIParameter, functionData: FunctionArtifact) { - const typename = getTypeName(param, functionData.name); - return `${param.name}: ${typename}`; -} - -/** - * Collects all parameters for a given function and flattens them according to how they should be serialized. - * @param parameters - Parameters for a function. - * @returns List of parameters flattened to basic data types. - */ -function collectParametersForSerialization(parameters: ABIVariable[]) { - const flattened: string[] = []; - for (const parameter of parameters) { - const { name } = parameter; - if (parameter.type.kind === 'array') { - const nestedType = parameter.type.type; - const nested = times(parameter.type.length, i => - collectParametersForSerialization([{ name: `${name}[${i}]`, type: nestedType }]), - ); - flattened.push(...nested.flat()); - } else if (parameter.type.kind === 'struct') { - const nested = parameter.type.fields.map(field => - collectParametersForSerialization([{ name: `${name}.${field.name}`, type: field.type }]), - ); - flattened.push(...nested.flat()); - } else if (parameter.type.kind === 'string') { - throw new Error(`String not yet supported`); - } else if (parameter.type.kind === 'field') { - flattened.push(name); - } else { - flattened.push(`${name} as Field`); - } - } - return flattened; -} - -/** - * Generates Noir code for serializing the parameters into an array of fields. - * @param parameters - Parameters to serialize. - * @returns The serialization code. - */ -function generateSerialization(parameters: ABIParameter[]) { - const flattened = collectParametersForSerialization(parameters); - const declaration = ` let mut serialized_args = [0; ${flattened.length}];`; - const lines = flattened.map((param, i) => ` serialized_args[${i}] = ${param};`); - return [declaration, ...lines].join('\n'); -} - -/** - * Generate a function interface for a particular function of the Aztec.nr Contract being processed. This function will be a method of the ContractInterface struct being created here. - * @param functionData - Data relating to the function, which can be used to generate a callable Aztec.nr Function. - * @param kind - Whether this interface will be used from private or public functions. - * @returns A code string. - */ -function generateFunctionInterface(functionData: FunctionArtifact, kind: 'private' | 'public') { - const { name, parameters } = functionData; - const selector = FunctionSelector.fromNameAndParameters(name, parameters); - const serialization = generateSerialization(parameters); - const contextType = kind === 'private' ? '&mut PrivateContext' : '&mut PublicContext'; - const callStatement = generateCallStatement(selector, functionData.functionType, kind); - const allParams = ['self', `context: ${contextType}`, ...parameters.map(p => generateParameter(p, functionData))]; - const isPrivate = isPrivateCall(functionData.functionType); - const isSync = (isPrivate && kind === 'private') || (!isPrivate && kind === 'public'); - // TODO: When return typing data is available in the artifact, we can instead codegen the concrete return type for public and private. - const generics = !isPrivate && isSync ? `` : ``; - const retType = isPrivate ? `-> PackedReturns` : isSync ? `-> FunctionReturns ` : ``; - - return ` - pub fn ${name}${generics}( - ${allParams.join(',\n ')} - ) ${retType}{ -${serialization} -${callStatement} - } - `; -} - -/** - * Generates static imports. - * @returns A string of code which will be needed in every contract interface, regardless of the contract. - */ -function generateStaticImports() { - return `use dep::std; -use dep::aztec::context::{ PrivateContext, PublicContext, PackedReturns, FunctionReturns, gas::GasOpts }; -use dep::aztec::protocol_types::{ - address::AztecAddress, - abis::function_selector::FunctionSelector, -};`; -} - -/** - * Generates the name of the contract struct, based on whether it's for private or public usage. - * @param contractName - Name of the contract. - * @param kind - Whether this interface will be used from private or public functions. - * @returns A name. - */ -function generateContractStructName(contractName: string, kind: 'private' | 'public') { - return `${contractName}${capitalize(kind)}ContextInterface`; -} - -/** - * Generate the main focus of this code generator: the contract interface struct. - * @param contractName - the name of the contract, as matches the original source file. - * @param kind - Whether this interface will be used from private or public functions. - * @returns Code. - */ -function generateContractInterfaceStruct(contractName: string, kind: 'private' | 'public') { - return `// Interface for calling ${contractName} functions from a ${kind} context -struct ${generateContractStructName(contractName, kind)} { - address: AztecAddress, -} -`; -} - -/** - * Generates the implementation of the contract interface struct. - * @param contractName - The name of the contract, as matches the original source file. - * @param kind - Whether this interface will be used from private or public functions. - * @param functions - An array of strings, where each string is valid Noir code describing the function interface of one of the contract's functions (as generated via `generateFunctionInterface` above). - * @returns Code. - */ -function generateContractInterfaceImpl(contractName: string, kind: 'private' | 'public', functions: string[]) { - return `impl ${generateContractStructName(contractName, kind)} { - pub fn at(address: AztecAddress) -> Self { - Self { - address, - } - } - ${functions.join('\n')} -} -`; -} - -/** Represents a struct along its parent names to derive a fully qualified name. */ -type StructInfo = ABIVariable & { /** Parent name */ parentNames: string[] }; - -/** - * Generates a Noir struct. - * @param struct - Struct info. - * @returns Code representing the struct. - */ -function generateStruct(struct: StructInfo) { - const fields = (struct.type as StructType).fields.map( - field => ` ${field.name}: ${getTypeName(field, struct.name, ...struct.parentNames)},`, - ); - - return ` -struct ${getStructName(struct.name, ...struct.parentNames)} { -${fields.join('\n')} -}`; -} - -/** - * Collects all structs across all parameters. - * @param params - Parameters to look for structs, either structs themselves or nested. - * @param parentNames - Parent names to derive fully qualified names when needed. - * @returns A list of struct infos. - */ -function collectStructs(params: ABIVariable[], parentNames: string[]): StructInfo[] { - const structs: StructInfo[] = []; - for (const param of params) { - if (param.type.kind === 'struct') { - const struct = { ...param, parentNames }; - structs.push(struct, ...collectStructs(param.type.fields, [param.name, ...parentNames])); - } else if (param.type.kind === 'array') { - structs.push(...collectStructs([{ name: param.name, type: param.type.type }], [...parentNames])); - } - } - return structs; -} - -/** - * Generates the struct definition and implementation for a contract interface. - * @param abiName - Name of the contract. - * @param kind - Whether this interface will be used from private or public functions. - * @param methods - Contract methods to generate (private ones will be excluded if kind is public) - * @returns Code. - */ -function generateContractStruct(abiName: string, kind: 'private' | 'public', methods: FunctionArtifact[]) { - const contractStruct: string = generateContractInterfaceStruct(abiName, kind); - const applicableMethods = methods.filter(m => kind === 'private' || !isPrivateCall(m.functionType)); - const functionInterfaces = applicableMethods.map(m => generateFunctionInterface(m, kind)); - const contractImpl: string = generateContractInterfaceImpl(abiName, kind, functionInterfaces); - - return ` -${contractStruct} -${contractImpl} - `; -} - -/** - * Generates the Noir code to represent an interface for calling a contract. - * @param artifact - The compiled Aztec.nr artifact. - * @returns The corresponding ts code. - */ -export function generateNoirContractInterface(artifact: ContractArtifact) { - // We don't allow calling internal fns or unconstrained fns from other contracts - const methods = artifact.functions.filter(f => !f.isInternal && f.functionType !== FunctionType.UNCONSTRAINED); - const paramStructs = methods.flatMap(m => collectStructs(m.parameters, [m.name])).map(generateStruct); - const privateContractStruct = generateContractStruct(artifact.name, 'private', methods); - const publicContractStruct = generateContractStruct(artifact.name, 'public', methods); - - return `/* Autogenerated file, do not edit! */ - -${generateStaticImports()} -${paramStructs.join('\n')} - -${privateContractStruct} - -${publicContractStruct} -`; -} diff --git a/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts b/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts index 0ade1726ec8..04f1af32ed4 100644 --- a/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts +++ b/yarn-project/noir-compiler/src/contract-interface-gen/typescript.ts @@ -14,6 +14,8 @@ import { isWrappedFieldStruct, } from '@aztec/foundation/abi'; +import uniqBy from 'lodash.uniqby'; + /** * Returns the corresponding typescript type for a given Noir type. * @param type - The input Noir type. @@ -224,7 +226,9 @@ function generateStorageLayoutGetter(input: ContractArtifact) { * @param input - The contract artifact. */ function generateNotesGetter(input: ContractArtifact) { - const notes = input.outputs.globals.notes ? (input.outputs.globals.notes as TupleValue[]) : []; + const notes = input.outputs.globals.notes + ? uniqBy(input.outputs.globals.notes as TupleValue[], n => (n.fields[1] as BasicValue<'string', string>).value) + : []; const notesUnionType = notes.map(n => `'${(n.fields[1] as BasicValue<'string', string>).value}'`).join(' | '); const noteMetadata = notes diff --git a/yarn-project/noir-compiler/src/index.ts b/yarn-project/noir-compiler/src/index.ts index a28e4f09303..c6c4a84e441 100644 --- a/yarn-project/noir-compiler/src/index.ts +++ b/yarn-project/noir-compiler/src/index.ts @@ -1,2 +1 @@ export { generateTypescriptContractInterface } from './contract-interface-gen/typescript.js'; -export { generateNoirContractInterface } from './contract-interface-gen/noir.js'; diff --git a/yarn-project/noir-contracts.js/scripts/generate-noir-interfaces.sh b/yarn-project/noir-contracts.js/scripts/generate-noir-interfaces.sh deleted file mode 100755 index 249d168242f..00000000000 --- a/yarn-project/noir-contracts.js/scripts/generate-noir-interfaces.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -CONTRACTS=( - test_contract-Test -) - -NOIR_CONTRACTS_DIR="../../noir-projects/noir-contracts" - -for contract in $CONTRACTS; do - echo "Generating Noir interface for $contract" - OUT_DIR="$NOIR_CONTRACTS_DIR/contracts/${contract%%-*}/src" - node --no-warnings ../noir-compiler/dest/cli.js codegen -o $OUT_DIR --nr --force $NOIR_CONTRACTS_DIR/target/$contract.json - mv $OUT_DIR/${contract#*-}.nr $OUT_DIR/interface.nr -done - -echo "Done updating Noir interfaces" \ No newline at end of file diff --git a/yarn-project/noir-contracts.js/scripts/generate-types.sh b/yarn-project/noir-contracts.js/scripts/generate-types.sh index 87a13d3459d..6e98b09125b 100755 --- a/yarn-project/noir-contracts.js/scripts/generate-types.sh +++ b/yarn-project/noir-contracts.js/scripts/generate-types.sh @@ -28,7 +28,7 @@ for ABI in $(find ../../noir-projects/noir-contracts/target -maxdepth 1 -type f done # Generate types for the contracts -node --no-warnings ../noir-compiler/dest/cli.js codegen -o $OUT_DIR --ts artifacts +node --no-warnings ../noir-compiler/dest/cli.js codegen -o $OUT_DIR artifacts # Append exports for each generated TypeScript file to index.ts find "$OUT_DIR" -maxdepth 1 -type f -name '*.ts' ! -name 'index.ts' | while read -r TS_FILE; do diff --git a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap index 7c722a43ea3..4c0efd45b43 100644 --- a/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap +++ b/yarn-project/noir-protocol-circuits-types/src/__snapshots__/index.test.ts.snap @@ -35,20 +35,20 @@ PrivateKernelCircuitPublicInputs { "constants": CombinedConstantData { "gasSettings": GasSettings { "da": DimensionGasSettings { - "gasLimit": 0, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "teardownGasLimit": 0, + "gasLimit": 1000000000, + "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, + "teardownGasLimit": 100000000, }, - "inclusionFee": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "inclusionFee": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, "l1": DimensionGasSettings { - "gasLimit": 0, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "teardownGasLimit": 0, + "gasLimit": 1000000000, + "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, + "teardownGasLimit": 100000000, }, "l2": DimensionGasSettings { - "gasLimit": 0, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "teardownGasLimit": 0, + "gasLimit": 1000000000, + "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, + "teardownGasLimit": 100000000, }, }, "historicalHeader": Header { @@ -56,7 +56,7 @@ PrivateKernelCircuitPublicInputs { "inHash": Buffer<0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c>, "outHash": Buffer<0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3>, "txTreeHeight": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, - "txsEffectsHash": Buffer<0x009f88379d44d0a51bbcabe282c4a95d4d557f32ee6504222f98fac65c836ef8>, + "txsEffectsHash": Buffer<0x007710847c110c9d1d2feb57e05a986dfb30c2d33811a9d05c76c9657af34d07>, }, "globalVariables": { "blockNumber": "0x0000000000000000000000000000000000000000000000000000000000000003", @@ -68,12 +68,12 @@ PrivateKernelCircuitPublicInputs { "feePerL1Gas": "0x0000000000000000000000000000000000000000000000000000000000000001", "feePerL2Gas": "0x0000000000000000000000000000000000000000000000000000000000000001", }, - "timestamp": "0x000000000000000000000000000000000000000000000000000000006619ac6e", + "timestamp": "0x00000000000000000000000000000000000000000000000000000000661e94db", "version": "0x0000000000000000000000000000000000000000000000000000000000000001", }, "lastArchive": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 3, - "root": Fr<0x0d73b8dcb63644da3ce1cc4b72ce47a9011e4ee6fcadddd072669e8874520e88>, + "root": Fr<0x0eed5cdbaafbbc794dbfae12e568d38ba22a9c222066df87fd213f7c5240117e>, }, "state": StateReference { "l1ToL2MessageTree": AppendOnlyTreeSnapshot { @@ -83,11 +83,11 @@ PrivateKernelCircuitPublicInputs { "partial": PartialStateReference { "noteHashTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 384, - "root": Fr<0x0c8f36d51e7c4d4764693616ce61b40443e51e4b0671e653a283778f3f38ef63>, + "root": Fr<0x234676c856daf7c0bf73f0e9a3980387c0a78cceb1be03d3b9542ad31ebfa1d8>, }, "nullifierTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 512, - "root": Fr<0x27c729d136d77fc9ee9ae8826e430102e8179b0352860a27897475deb4789d4d>, + "root": Fr<0x00d1d7b14ec97e9e3332c3eb5734202d6e3a0c76b3a7de8a05a857d7c885ae0e>, }, "publicDataTree": AppendOnlyTreeSnapshot { "nextAvailableLeafIndex": 256, @@ -105,7 +105,40 @@ PrivateKernelCircuitPublicInputs { }, "end": PrivateAccumulatedData { "encryptedLogPreimagesLength": Fr<0x000000000000000000000000000000000000000000000000000000000000000c>, - "encryptedLogsHash": Fr<0x00f33ae280239814c4dfaaafc16fc138a8d3eae52bb962af6576cbb61c2af246>, + "encryptedLogsHashes": [ + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + ], "gasUsed": Gas { "daGas": 0, "l1Gas": 0, @@ -377,7 +410,7 @@ PrivateKernelCircuitPublicInputs { SideEffectLinkedToNoteHash { "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, "noteHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "value": Fr<0x1880aed672696b500b0b9aecfd6dc4514db66fe4f2b7e1eced3890792361e5de>, + "value": Fr<0x1cbfe3e489299947cef42ee1812ff6b238b856ae13f95437b82ce86f44fe4fb6>, }, SideEffectLinkedToNoteHash { "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, @@ -860,7 +893,40 @@ PrivateKernelCircuitPublicInputs { }, ], "unencryptedLogPreimagesLength": Fr<0x000000000000000000000000000000000000000000000000000000000000000c>, - "unencryptedLogsHash": Fr<0x00f33ae280239814c4dfaaafc16fc138a8d3eae52bb962af6576cbb61c2af246>, + "unencryptedLogsHashes": [ + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + SideEffect { + "counter": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "value": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + }, + ], }, "minRevertibleSideEffectCounter": Fr<0x0000000000000000000000000000000000000000000000000000000000000002>, "validationRequests": ValidationRequests { @@ -1707,20 +1773,20 @@ PrivateKernelTailCircuitPublicInputs { "constants": CombinedConstantData { "gasSettings": GasSettings { "da": DimensionGasSettings { - "gasLimit": 0, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "teardownGasLimit": 0, + "gasLimit": 1000000000, + "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, + "teardownGasLimit": 100000000, }, - "inclusionFee": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, + "inclusionFee": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, "l1": DimensionGasSettings { - "gasLimit": 0, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "teardownGasLimit": 0, + "gasLimit": 1000000000, + "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, + "teardownGasLimit": 100000000, }, "l2": DimensionGasSettings { - "gasLimit": 0, - "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, - "teardownGasLimit": 0, + "gasLimit": 1000000000, + "maxFeePerGas": Fr<0x0000000000000000000000000000000000000000000000000000000000000001>, + "teardownGasLimit": 100000000, }, }, "historicalHeader": Header { @@ -1779,7 +1845,7 @@ PrivateKernelTailCircuitPublicInputs { "forRollup": PartialPrivateTailPublicInputsForRollup { "end": CombinedAccumulatedData { "encryptedLogPreimagesLength": Fr<0x000000000000000000000000000000000000000000000000000000000000013c>, - "encryptedLogsHash": Fr<0x006b84c144df926035cff13e0fb09ba4d9a3ee630a19e337070937cebe54a142>, + "encryptedLogsHash": Fr<0x0071e599f47dc5bf086c58651ed033ba8cc6a92633997f5170cca8c19acee03b>, "gasUsed": Gas { "daGas": 0, "l1Gas": 0, @@ -1790,7 +1856,7 @@ PrivateKernelTailCircuitPublicInputs { Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, ], "newNoteHashes": [ - Fr<0x19bf43108e47e7de12dfc5b64b4c654948d5f3fab57fb5f8656c755f77a7abdd>, + Fr<0x07cb8cd31632ab31e7c957add2d3a061122405360982009a0e7fb1d5a1488539>, Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, @@ -1856,9 +1922,9 @@ PrivateKernelTailCircuitPublicInputs { Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, ], "newNullifiers": [ - Fr<0x04c7ecd5d2f178611681297a008901bfe783c6a31e23f58f1610e2e5ae4c3ce3>, - Fr<0x2c391fb5b3309c990b808765e989268195f732146a90adbcbdb14a1ed8f5265f>, - Fr<0x1c2ce60b74b4f12fe8f7ca2070458aaf50cffeb38ada523fd775a2c13183311c>, + Fr<0x26fd8601b83cf50cefc8fd01a8f4f257818b236b4b05a4d655d1e250617cca47>, + Fr<0x239e2829a14b926fda5538c945938ffb2d69bca6532cf8d9ef8cb03654928c21>, + Fr<0x1ad338c82a5771b8c493d4fdd310e05a947584891295750cc1267bc96bbd0cde>, Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, @@ -2084,7 +2150,7 @@ PrivateKernelTailCircuitPublicInputs { }, ], "unencryptedLogPreimagesLength": Fr<0x0000000000000000000000000000000000000000000000000000000000000008>, - "unencryptedLogsHash": Fr<0x008d4d695766a616808caa331119da14269ac3271c251dec3a11df896131ba2c>, + "unencryptedLogsHash": Fr<0x0000000000000000000000000000000000000000000000000000000000000000>, }, "rollupValidationRequests": RollupValidationRequests { "maxBlockNumber": MaxBlockNumber { diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex index 4edb9086806..35212bb487c 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-init.hex @@ -1 +1 @@ -1542e706b7d400b46fa10f5a5d1f25970d34feff6e9e23a55422f6e4c5ae84b637889ba1011751bdf6c6325cac78c13a6518b58a1d538f2ee71dc34d3822258669a89ca2c300000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001542e706b7d400b46fa10f5a5d1f25970d34feff6e9e23a55422f6e4c5ae84b637889ba10100000000000000000000000000000000000000000000000000000000000000001542e706b7d400b46fa10f5a5d1f25970d34feff6e9e23a55422f6e4c5ae84b6000000000000000000000000000000000000000037889ba1000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001751bdf6c6325cac78c13a6518b58a1d538f2ee71dc34d3822258669a89ca2c3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f34fe96f4f0474d57f53c2abc41d0524a12d21d02f413ff1da1b704638d3cd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b800e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b80000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010f34fe96f4f0474d57f53c2abc41d0524a12d21d02f413ff1da1b704638d3cd01542e706b7d400b46fa10f5a5d1f25970d34feff6e9e23a55422f6e4c5ae84b600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f27a6bc6f7d8adc5027a61509e26a35f7de8d2f48c8f5511588460e1715c7be551dae27cc7fe2af345f160253be3875d449a7e9ba6bd68747d87d4e7054b8111527b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed19ffad41d477b4d4077d3edfe7eaf592f3b332d915dc68b41f2f1f370ebed632000000000000000000000000000000000000000000000000000000000000000027b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a715500bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +1166f8313bdcd368a148663939fd38eb6a6500a577435b5a433ff0357ca8b15937889ba10104fe385bb1c80a41d917a6f6061312dc211638616c9da820eb5bca522bc8996500000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000011166f8313bdcd368a148663939fd38eb6a6500a577435b5a433ff0357ca8b15937889ba10100000000000000000000000000000000000000000000000000000000000000001166f8313bdcd368a148663939fd38eb6a6500a577435b5a433ff0357ca8b159000000000000000000000000000000000000000037889ba135a4e90035a4e90035a4e9000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000004fe385bb1c80a41d917a6f6061312dc211638616c9da820eb5bca522bc89965000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001019e4c3aa9b03aa5bf974d1954b5e219db2b0e1d42a4ed9f095c102eb2157d7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000011019e4c3aa9b03aa5bf974d1954b5e219db2b0e1d42a4ed9f095c102eb2157d71166f8313bdcd368a148663939fd38eb6a6500a577435b5a433ff0357ca8b15900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1568448ac2259bbec7694d6670a15177bd0304d71700aa7fea107740a077d0411dae27cc7fe2af345f160253be3875d449a7e9ba6bd68747d87d4e7054b8111527b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed19ffad41d477b4d4077d3edfe7eaf592f3b332d915dc68b41f2f1f370ebed632000000000000000000000000000000000000000000000000000000000000000027b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed21dbfd1d029bf447152fcf89e355c334610d1632436ba170f738107266a715500bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex index 733be30a064..3b12c7db785 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-inner.hex @@ -1 +1 @@ -0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be20000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001880aed672696b500b0b9aecfd6dc4514db66fe4f2b7e1eced3890792361e5de0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d4d695766a616808caa331119da14269ac3271c251dec3a11df896131ba2c008d4d695766a616808caa331119da14269ac3271c251dec3a11df896131ba2c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000082ed55d9a77c69f79c676dd08389c15a7cef535cbeb79c0bc0e2b2281bf5a4ee625d9fa771a71f0bdf81ef098310c1a85781ba9f1d6a48a86c31a8e32f007b44900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d73b8dcb63644da3ce1cc4b72ce47a9011e4ee6fcadddd072669e8874520e88000000030000000000000000000000000000000000000000000000000000000000000001009f88379d44d0a51bbcabe282c4a95d4d557f32ee6504222f98fac65c836ef800089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000300c8f36d51e7c4d4764693616ce61b40443e51e4b0671e653a283778f3f38ef630000018027c729d136d77fc9ee9ae8826e430102e8179b0352860a27897475deb4789d4d000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000006619ac6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0000000027c5fe4e30f75253cf4da921a648af377a2a2488c7a8dafc4dada7a36744dead2476fe960a5df72a0a135ecfa44f16c4340253a6f0aeb08f3baa54e97fa4f811126bf8c85bf3ad7f0dc949a9f8dfeadcdf19c4f1e8d2de07f3322ea27b9d752b0b48a6b62ea408a1d3c4d2c00b439d8926a87ef37a7c6c4f37df06ef2346eead0906bca10125d9fa771a71f0bdf81ef098310c1a85781ba9f1d6a48a86c31a8e32f007b4490b48a6b62ea408a1d3c4d2c00b439d8926a87ef37a7c6c4f37df06ef2346eead00000000000000000000000000000000000000000906bca1000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002898402da2fa95f47c47763fe5b171ff3155bd31e5af88d9823bccb26b6701542451ab56341b4067780469e41818b47f8fd45f4bd186f22ba4b4a1bb5d45a42d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000300e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b800e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040d73b8dcb63644da3ce1cc4b72ce47a9011e4ee6fcadddd072669e8874520e88000000030000000000000000000000000000000000000000000000000000000000000001009f88379d44d0a51bbcabe282c4a95d4d557f32ee6504222f98fac65c836ef800089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000300c8f36d51e7c4d4764693616ce61b40443e51e4b0671e653a283778f3f38ef630000018027c729d136d77fc9ee9ae8826e430102e8179b0352860a27897475deb4789d4d000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000006619ac6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f1ff0a9b7a099d594bd0e354559eaf907024832a34103de4f6c7251392bdc4db12e83474780e15780013d0979caacfa35001c8b9105480f1ad1e448b46edb1f5b27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed18de29b683be958b594c2aeed5ee41e2f5afdb1ee459a090cb2f49ab6edc73ed00000000000000000000000000000000000000000000000000000000000000002452a14c748981acff167dba9088770b6c2c2dc34677295a1974f2c247236ba11e904e4d0a67667f8faaa89198f5e89684e213bc99a83c3b20888d5854d3dd320bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be20000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001cbfe3e489299947cef42ee1812ff6b238b856ae13f95437b82ce86f44fe4fb600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008184e3ae016e6a45c309f1d04c50823f260cc02e2f4b5c9d8bf7cd10d8dc1c6e3304faeaac4852e3721a5f76646d8f1bcf4e1cf8e6f4795a6a0053d7540aff67900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eed5cdbaafbbc794dbfae12e568d38ba22a9c222066df87fd213f7c5240117e000000030000000000000000000000000000000000000000000000000000000000000001007710847c110c9d1d2feb57e05a986dfb30c2d33811a9d05c76c9657af34d0700089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030234676c856daf7c0bf73f0e9a3980387c0a78cceb1be03d3b9542ad31ebfa1d80000018000d1d7b14ec97e9e3332c3eb5734202d6e3a0c76b3a7de8a05a857d7c885ae0e000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000661e94db0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0000000020a37986ee9aa91cfe3a609b350e6d266999461b635ca0420b884b08d50f4d1009c5c0728c89546b73fe3b9aa402e0ae562ce934b88235b388c690e5b0f20e8218cae2fa2e3faf92d1536361e486b34baad26a22d1253b821563a5a1003b20df15d54e8dde4393f502819821390cfd31ba0c912e86fbc2da32922256c53255f60906bca101304faeaac4852e3721a5f76646d8f1bcf4e1cf8e6f4795a6a0053d7540aff67915d54e8dde4393f502819821390cfd31ba0c912e86fbc2da32922256c53255f600000000000000000000000000000000000000000906bca135a4e90035a4e90035a4e9000000000000033b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e1000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002898402da2fa95f47c47763fe5b171ff3155bd31e5af88d9823bccb26b6701542451ab56341b4067780469e41818b47f8fd45f4bd186f22ba4b4a1bb5d45a42d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040eed5cdbaafbbc794dbfae12e568d38ba22a9c222066df87fd213f7c5240117e000000030000000000000000000000000000000000000000000000000000000000000001007710847c110c9d1d2feb57e05a986dfb30c2d33811a9d05c76c9657af34d0700089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f8000000030234676c856daf7c0bf73f0e9a3980387c0a78cceb1be03d3b9542ad31ebfa1d80000018000d1d7b14ec97e9e3332c3eb5734202d6e3a0c76b3a7de8a05a857d7c885ae0e000002000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000661e94db000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0de7a2fe9b5384b7142877d9ee77fb5bf7073902e711504a1ec4c7039b3ba35b2904908a7e8e4b61c07ee8c119b09ca8dc00cc6787e3dc5c4100c845d94b19cc27b1d0839a5b23baf12a8d195b18ac288fcf401afb2f70b8a4b529ede5fa9fed0ad428a44324ce02cf0c67cb517de63f73072ab8ab5295a9c1f394057bc9719500000000000000000000000000000000000000000000000000000000000000002452a14c748981acff167dba9088770b6c2c2dc34677295a1974f2c247236ba11e904e4d0a67667f8faaa89198f5e89684e213bc99a83c3b20888d5854d3dd320bcd1f91cf7bdd471d0a30c58c4706f3fdab3807a954b8f5b5e3bfec87d001bb06e62084ee7b602fe9abc15632dda3269f56fb0c6e12519a2eb2ec897091919d03c9e2e67178ac638746f068907e6677b4cc7a9592ef234ab6ab518f17efffa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex index ff5d1cbadd9..157f363bcb6 100644 --- a/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex +++ b/yarn-project/noir-protocol-circuits-types/src/fixtures/nested-call-private-kernel-ordering.hex @@ -1 +1 @@ -0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be200000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc196678c850931f1af7b0e5d9c8c9b07c7ac59feec028e8a45f17f8df257d2000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c7ecd5d2f178611681297a008901bfe783c6a31e23f58f1610e2e5ae4c3ce3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c391fb5b3309c990b808765e989268195f732146a90adbcbdb14a1ed8f5265f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011c2ce60b74b4f12fe8f7ca2070458aaf50cffeb38ada523fd775a2c13183311c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b84c144df926035cff13e0fb09ba4d9a3ee630a19e337070937cebe54a142008d4d695766a616808caa331119da14269ac3271c251dec3a11df896131ba2c000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b0000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f0000000005e0566380cae864789402b085109bc5cc887555db8a6d1993ae821535ce56100795bfddf7dcb8a2c422133c34fbdc6175c8c44fb63e165904520f4284f478bc0c359b7060c5240c5ddcb1d8b2b129bfb487b4cf2198eb1c12c3bf7da937efb30dc196678c850931f1af7b0e5d9c8c9b07c7ac59feec028e8a45f17f8df257d20000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c7ecd5d2f178611681297a008901bfe783c6a31e23f58f1610e2e5ae4c3ce3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002c391fb5b3309c990b808765e989268195f732146a90adbcbdb14a1ed8f5265f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011c2ce60b74b4f12fe8f7ca2070458aaf50cffeb38ada523fd775a2c13183311c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file +0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000001000000bd300000bd400000bd500000bd600000bd700000bd800000bd900000bda00000bdb00000bdc00000bdd00000bde00000bdf00000be000000be100000be2000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022a0c845d11f6ab935270159fcf81cf8fc6c19ba959855941ea0a910dfccb0aa000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026fd8601b83cf50cefc8fd01a8f4f257818b236b4b05a4d655d1e250617cca4700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000239e2829a14b926fda5538c945938ffb2d69bca6532cf8d9ef8cb03654928c21000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011ad338c82a5771b8c493d4fdd310e05a947584891295750cc1267bc96bbd0cde0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c86d02eb4dc898abeefc07e126614d7342bc55f1bb250a211861dfe87f8e30000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013c000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000000016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000000800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b0000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e10000000000000000000000000000000000000000000000000000000000000000013b9aca0005f5e100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000002a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000740000000f00000003515f3109623eb3c25aa5b16a1a79fd558bac7a7ce62c4560a8c537c77ce80dd339128d1d37b6582ee9e6df9567efb64313471dfa18f520f9ce53161b50dbf7731bc5f900000003515f322bc4cce83a486a92c92fd59bd84e0f92595baa639fc2ed86b00ffa0dfded2a092a669a3bdb7a273a015eda494457cc7ed5236f26cee330c290d45a33b9daa94800000003515f332729426c008c085a81bd34d8ef12dd31e80130339ef99d50013a89e4558eee6d0fa4ffe2ee7b7b62eb92608b2251ac31396a718f9b34978888789042b790a30100000003515f342be6b6824a913eb7a57b03cb1ee7bfb4de02f2f65fe8a4e97baa7766ddb353a82a8a25c49dc63778cd9fe96173f12a2bc77f3682f4c4448f98f1df82c75234a100000003515f351f85760d6ab567465aadc2f180af9eae3800e6958fec96aef53fd8a7b195d7c000c6267a0dd5cfc22b3fe804f53e266069c0e36f51885baec1e7e67650c62e170000000c515f41524954484d455449430d9d0f8ece2aa12012fa21e6e5c859e97bd5704e5c122064a66051294bc5e04213f61f54a0ebdf6fee4d4a6ecf693478191de0c2899bcd8e86a636c8d3eff43400000003515f43224a99d02c86336737c8dd5b746c40d2be6aead8393889a76a18d664029096e90f7fe81adcc92a74350eada9622ac453f49ebac24a066a1f83b394df54dfa0130000000c515f46495845445f42415345060e8a013ed289c2f9fd7473b04f6594b138ddb4b4cf6b901622a14088f04b8d2c83ff74fce56e3d5573b99c7b26d85d5046ce0c6559506acb7a675e7713eb3a00000007515f4c4f4749430721a91cb8da4b917e054f72147e1760cfe0ef3d45090ac0f4961d84ec1996961a25e787b26bd8b50b1a99450f77a424a83513c2b33af268cd253b0587ff50c700000003515f4d05dbd8623b8652511e1eb38d38887a69eceb082f807514f09e127237c5213b401b9325b48c6c225968002318095f89d0ef9cf629b2b7f0172e03bc39aacf6ed800000007515f52414e474504b57a3805e41df328f5ca9aefa40fad5917391543b7b65c6476e60b8f72e9ad07c92f3b3e11c8feae96dedc4b14a6226ef3201244f37cfc1ee5b96781f48d2b000000075349474d415f3125001d1954a18571eaa007144c5a567bb0d2be4def08a8be918b8c05e3b27d312c59ed41e09e144eab5de77ca89a2fd783be702a47c951d3112e3de02ce6e47c000000075349474d415f3223994e6a23618e60fa01c449a7ab88378709197e186d48d604bfb6931ffb15ad11c5ec7a0700570f80088fd5198ab5d5c227f2ad2a455a6edeec024156bb7beb000000075349474d415f3300cda5845f23468a13275d18bddae27c6bb189cf9aa95b6a03a0cb6688c7e8d829639b45cf8607c525cc400b55ebf90205f2f378626dc3406cc59b2d1b474fba000000075349474d415f342d299e7928496ea2d37f10b43afd6a80c90a33b483090d18069ffa275eedb2fc2f82121e8de43dc036d99b478b6227ceef34248939987a19011f065d8b5cef5c0000000010000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000002013d0ff20211fe37493ef7ae818718fe839086139dccdf57e3d07f2d179e0802ad66b73a8b9536005aacaca6c565759426bcacd052db1d07f4fa5912f5731b52c52764f15c29eb4d74bd670e65ac533b62d805ac395adba6d7e074e991116a522a0c845d11f6ab935270159fcf81cf8fc6c19ba959855941ea0a910dfccb0aa0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026fd8601b83cf50cefc8fd01a8f4f257818b236b4b05a4d655d1e250617cca4700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000239e2829a14b926fda5538c945938ffb2d69bca6532cf8d9ef8cb03654928c21000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011ad338c82a5771b8c493d4fdd310e05a947584891295750cc1267bc96bbd0cde00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000f000000100000001100000012000000130000001400000015000000160000001700000018000000190000001a0000001b0000001c0000001d0000001e0000001f000000200000002100000022000000230000002400000025000000260000002700000028000000290000002a0000002b0000002c0000002d0000002e0000002f000000300000003100000032000000330000003400000035000000360000003700000038000000390000003a0000003b0000003c0000003d0000003e0000003f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000800000000000000080000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c86d02eb4dc898abeefc07e126614d7342bc55f1bb250a211861dfe87f8e30000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000020000000300000004000000050000000600000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000200000003000000040000000500000006000000070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index 0dbf841e51e..d69b24594e0 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -31,6 +31,8 @@ import { KernelCircuitPublicInputs, type KernelData, type L2ToL1Message, + type LeafDataReadHint, + MAX_ENCRYPTED_LOGS_PER_TX, MAX_NEW_L2_TO_L1_MSGS_PER_TX, MAX_NEW_NOTE_HASHES_PER_TX, MAX_NEW_NULLIFIERS_PER_TX, @@ -42,6 +44,7 @@ import { MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, MaxBlockNumber, type MembershipWitness, type MergeRollupInputs, @@ -76,7 +79,9 @@ import { type PublicCallData, type PublicCallStackItem, type PublicCircuitPublicInputs, + type PublicDataHint, PublicDataRead, + type PublicDataReadRequestHints, type PublicDataTreeLeaf, type PublicDataTreeLeafPreimage, PublicDataUpdateRequest, @@ -170,8 +175,11 @@ import { type StorageUpdateRequest as StorageUpdateRequestNoir, } from './types/public_kernel_setup_types.js'; import { + type LeafDataReadHint as LeafDataReadHintNoir, type NullifierNonExistentReadRequestHints as NullifierNonExistentReadRequestHintsNoir, type NullifierNonMembershipHint as NullifierNonMembershipHintNoir, + type PublicDataHint as PublicDataHintNoir, + type PublicDataReadRequestHints as PublicDataReadRequestHintsNoir, type PublicDataUpdateRequest as PublicDataUpdateRequestNoir, type PublicKernelTailCircuitPrivateInputs as PublicKernelTailCircuitPrivateInputsNoir, } from './types/public_kernel_tail_types.js'; @@ -736,8 +744,8 @@ export function mapPrivateCircuitPublicInputsToNoir( new_l2_to_l1_msgs: mapTuple(privateCircuitPublicInputs.newL2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.startSideEffectCounter), end_side_effect_counter: mapFieldToNoir(privateCircuitPublicInputs.endSideEffectCounter), - encrypted_logs_hash: mapFieldToNoir(privateCircuitPublicInputs.encryptedLogsHash), - unencrypted_logs_hash: mapFieldToNoir(privateCircuitPublicInputs.unencryptedLogsHash), + encrypted_logs_hashes: mapTuple(privateCircuitPublicInputs.encryptedLogsHashes, mapSideEffectToNoir), + unencrypted_logs_hashes: mapTuple(privateCircuitPublicInputs.unencryptedLogsHashes, mapSideEffectToNoir), encrypted_log_preimages_length: mapFieldToNoir(privateCircuitPublicInputs.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(privateCircuitPublicInputs.unencryptedLogPreimagesLength), historical_header: mapHeaderToNoir(privateCircuitPublicInputs.historicalHeader), @@ -926,6 +934,13 @@ function mapPendingReadHintToNoir(hint: PendingReadHint): PendingReadHintNoir { }; } +function mapLeafDataReadHintToNoir(hint: LeafDataReadHint): LeafDataReadHintNoir { + return { + read_request_index: mapNumberToNoir(hint.readRequestIndex), + data_hint_index: mapNumberToNoir(hint.dataHintIndex), + }; +} + function mapNullifierSettledReadHintToNoir( hint: SettledReadHint, ): NullifierSettledReadHintNoir { @@ -964,6 +979,24 @@ function mapNullifierNonExistentReadRequestHintsToNoir( }; } +function mapPublicDataHintToNoir(hint: PublicDataHint): PublicDataHintNoir { + return { + leaf_slot: mapFieldToNoir(hint.leafSlot), + value: mapFieldToNoir(hint.value), + override_counter: mapNumberToNoir(hint.overrideCounter), + membership_witness: mapPublicDataMembershipWitnessToNoir(hint.membershipWitness), + leaf_preimage: mapPublicDataTreePreimageToNoir(hint.leafPreimage), + }; +} + +function mapPublicDataReadRequestHintsToNoir(hints: PublicDataReadRequestHints): PublicDataReadRequestHintsNoir { + return { + read_request_statuses: mapTuple(hints.readRequestStatuses, mapReadRequestStatusToNoir), + pending_read_hints: mapTuple(hints.pendingReadHints, mapPendingReadHintToNoir), + leaf_data_read_hints: mapTuple(hints.leafDataReadHints, mapLeafDataReadHintToNoir), + }; +} + function mapValidationRequestsToNoir(requests: ValidationRequests): ValidationRequestsNoir { return { for_rollup: mapRollupValidationRequestsToNoir(requests.forRollup), @@ -1011,8 +1044,12 @@ export function mapPrivateAccumulatedDataFromNoir( mapTupleFromNoir(privateAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapSideEffectFromNoir), mapTupleFromNoir(privateAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapSideEffectLinkedFromNoir), mapTupleFromNoir(privateAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), - mapFieldFromNoir(privateAccumulatedData.encrypted_logs_hash), - mapFieldFromNoir(privateAccumulatedData.unencrypted_logs_hash), + mapTupleFromNoir(privateAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapSideEffectFromNoir), + mapTupleFromNoir( + privateAccumulatedData.unencrypted_logs_hashes, + MAX_UNENCRYPTED_LOGS_PER_TX, + mapSideEffectFromNoir, + ), mapFieldFromNoir(privateAccumulatedData.encrypted_log_preimages_length), mapFieldFromNoir(privateAccumulatedData.unencrypted_log_preimages_length), mapTupleFromNoir( @@ -1034,8 +1071,8 @@ export function mapPrivateAccumulatedDataToNoir(data: PrivateAccumulatedData): P new_note_hashes: mapTuple(data.newNoteHashes, mapSideEffectToNoir), new_nullifiers: mapTuple(data.newNullifiers, mapSideEffectLinkedToNoir), new_l2_to_l1_msgs: mapTuple(data.newL2ToL1Msgs, mapFieldToNoir), - encrypted_logs_hash: mapFieldToNoir(data.encryptedLogsHash), - unencrypted_logs_hash: mapFieldToNoir(data.unencryptedLogsHash), + encrypted_logs_hashes: mapTuple(data.encryptedLogsHashes, mapSideEffectToNoir), + unencrypted_logs_hashes: mapTuple(data.unencryptedLogsHashes, mapSideEffectToNoir), encrypted_log_preimages_length: mapFieldToNoir(data.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(data.unencryptedLogPreimagesLength), private_call_stack: mapTuple(data.privateCallStack, mapCallRequestToNoir), @@ -1051,8 +1088,8 @@ export function mapPublicAccumulatedDataFromNoir( mapTupleFromNoir(publicAccumulatedData.new_note_hashes, MAX_NEW_NOTE_HASHES_PER_TX, mapSideEffectFromNoir), mapTupleFromNoir(publicAccumulatedData.new_nullifiers, MAX_NEW_NULLIFIERS_PER_TX, mapSideEffectLinkedFromNoir), mapTupleFromNoir(publicAccumulatedData.new_l2_to_l1_msgs, MAX_NEW_L2_TO_L1_MSGS_PER_TX, mapFieldFromNoir), - mapFieldFromNoir(publicAccumulatedData.encrypted_logs_hash), - mapFieldFromNoir(publicAccumulatedData.unencrypted_logs_hash), + mapTupleFromNoir(publicAccumulatedData.encrypted_logs_hashes, MAX_ENCRYPTED_LOGS_PER_TX, mapSideEffectFromNoir), + mapTupleFromNoir(publicAccumulatedData.unencrypted_logs_hashes, MAX_UNENCRYPTED_LOGS_PER_TX, mapSideEffectFromNoir), mapFieldFromNoir(publicAccumulatedData.encrypted_log_preimages_length), mapFieldFromNoir(publicAccumulatedData.unencrypted_log_preimages_length), mapTupleFromNoir( @@ -1076,8 +1113,8 @@ export function mapPublicAccumulatedDataToNoir( new_note_hashes: mapTuple(publicAccumulatedData.newNoteHashes, mapSideEffectToNoir), new_nullifiers: mapTuple(publicAccumulatedData.newNullifiers, mapSideEffectLinkedToNoir), new_l2_to_l1_msgs: mapTuple(publicAccumulatedData.newL2ToL1Msgs, mapFieldToNoir), - encrypted_logs_hash: mapFieldToNoir(publicAccumulatedData.encryptedLogsHash), - unencrypted_logs_hash: mapFieldToNoir(publicAccumulatedData.unencryptedLogsHash), + encrypted_logs_hashes: mapTuple(publicAccumulatedData.encryptedLogsHashes, mapSideEffectToNoir), + unencrypted_logs_hashes: mapTuple(publicAccumulatedData.unencryptedLogsHashes, mapSideEffectToNoir), encrypted_log_preimages_length: mapFieldToNoir(publicAccumulatedData.encryptedLogPreimagesLength), unencrypted_log_preimages_length: mapFieldToNoir(publicAccumulatedData.unencryptedLogPreimagesLength), public_data_update_requests: mapTuple( @@ -1221,6 +1258,7 @@ export function mapKernelCircuitPublicInputsFromNoir(inputs: KernelCircuitPublic mapRollupValidationRequestsFromNoir(inputs.rollup_validation_requests), mapCombinedAccumulatedDataFromNoir(inputs.end), mapCombinedConstantDataFromNoir(inputs.constants), + mapPartialStateReferenceFromNoir(inputs.start_state), mapRevertCodeFromNoir(inputs.revert_code), ); } @@ -1231,6 +1269,7 @@ export function mapKernelCircuitPublicInputsToNoir(inputs: KernelCircuitPublicIn rollup_validation_requests: mapRollupValidationRequestsToNoir(inputs.rollupValidationRequests), constants: mapCombinedConstantDataToNoir(inputs.constants), end: mapCombinedAccumulatedDataToNoir(inputs.end), + start_state: mapPartialStateReferenceToNoir(inputs.startState), revert_code: mapRevertCodeToNoir(inputs.revertCode), }; } @@ -1361,6 +1400,10 @@ export function mapPrivateKernelTailCircuitPrivateInputsToNoir( sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), nullifier_read_request_hints: mapNullifierReadRequestHintsToNoir(inputs.nullifierReadRequestHints), nullifier_commitment_hints: mapTuple(inputs.nullifierCommitmentHints, mapFieldToNoir), + sorted_encrypted_log_hashes: mapTuple(inputs.sortedEncryptedLogHashes, mapSideEffectToNoir), + sorted_encrypted_log_hashes_indexes: mapTuple(inputs.sortedEncryptedLogHashesIndexes, mapNumberToNoir), + sorted_unencrypted_log_hashes: mapTuple(inputs.sortedUnencryptedLogHashes, mapSideEffectToNoir), + sorted_unencrypted_log_hashes_indexes: mapTuple(inputs.sortedUnencryptedLogHashesIndexes, mapNumberToNoir), master_nullifier_secret_keys: mapTuple(inputs.masterNullifierSecretKeys, mapGrumpkinPrivateKeyToNoir), }; } @@ -1377,6 +1420,10 @@ export function mapPrivateKernelTailToPublicCircuitPrivateInputsToNoir( sorted_new_nullifiers_indexes: mapTuple(inputs.sortedNewNullifiersIndexes, mapNumberToNoir), nullifier_read_request_hints: mapNullifierReadRequestHintsToNoir(inputs.nullifierReadRequestHints), nullifier_commitment_hints: mapTuple(inputs.nullifierCommitmentHints, mapFieldToNoir), + sorted_encrypted_log_hashes: mapTuple(inputs.sortedEncryptedLogHashes, mapSideEffectToNoir), + sorted_encrypted_log_hashes_indexes: mapTuple(inputs.sortedEncryptedLogHashesIndexes, mapNumberToNoir), + sorted_unencrypted_log_hashes: mapTuple(inputs.sortedUnencryptedLogHashes, mapSideEffectToNoir), + sorted_unencrypted_log_hashes_indexes: mapTuple(inputs.sortedUnencryptedLogHashesIndexes, mapNumberToNoir), master_nullifier_secret_keys: mapTuple(inputs.masterNullifierSecretKeys, mapGrumpkinPrivateKeyToNoir), }; } @@ -1399,6 +1446,9 @@ export function mapPublicKernelTailCircuitPrivateInputsToNoir( nullifier_non_existent_read_request_hints: mapNullifierNonExistentReadRequestHintsToNoir( inputs.nullifierNonExistentReadRequestHints, ), + public_data_hints: mapTuple(inputs.publicDataHints, mapPublicDataHintToNoir), + public_data_read_request_hints: mapPublicDataReadRequestHintsToNoir(inputs.publicDataReadRequestHints), + start_state: mapPartialStateReferenceToNoir(inputs.startState), }; } @@ -1530,7 +1580,7 @@ export function mapPublicCircuitPublicInputsToNoir( new_l2_to_l1_msgs: mapTuple(publicInputs.newL2ToL1Msgs, mapL2ToL1MessageToNoir), start_side_effect_counter: mapFieldToNoir(publicInputs.startSideEffectCounter), end_side_effect_counter: mapFieldToNoir(publicInputs.endSideEffectCounter), - unencrypted_logs_hash: mapFieldToNoir(publicInputs.unencryptedLogsHash), + unencrypted_logs_hashes: mapTuple(publicInputs.unencryptedLogsHashes, mapSideEffectToNoir), unencrypted_log_preimages_length: mapFieldToNoir(publicInputs.unencryptedLogPreimagesLength), historical_header: mapHeaderToNoir(publicInputs.historicalHeader), prover_address: mapAztecAddressToNoir(publicInputs.proverAddress), diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 4bf498b96eb..88ae37c05d0 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -415,6 +415,28 @@ export class ProvingOrchestrator { // Executes the base rollup circuit and stored the output as intermediate state for the parent merge/root circuit // Executes the next level of merge if all inputs are available private async runBaseRollup(provingState: ProvingState | undefined, index: bigint, tx: TxProvingState) { + if ( + !tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash + .toBuffer() + .equals(tx.processedTx.encryptedLogs.hash()) + ) { + throw new Error( + `Encrypted logs hash mismatch: ${ + tx.baseRollupInputs.kernelData.publicInputs.end.encryptedLogsHash + } === ${Fr.fromBuffer(tx.processedTx.encryptedLogs.hash())}`, + ); + } + if ( + !tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash + .toBuffer() + .equals(tx.processedTx.unencryptedLogs.hash()) + ) { + throw new Error( + `Unencrypted logs hash mismatch: ${ + tx.baseRollupInputs.kernelData.publicInputs.end.unencryptedLogsHash + } === ${Fr.fromBuffer(tx.processedTx.unencryptedLogs.hash())}`, + ); + } if (!provingState?.verifyState()) { logger.debug('Not running base rollup, state invalid'); return; diff --git a/yarn-project/pxe/src/kernel_prover/hints_builder.ts b/yarn-project/pxe/src/kernel_prover/hints_builder.ts index f57f1d8c7b4..dea4ae58b96 100644 --- a/yarn-project/pxe/src/kernel_prover/hints_builder.ts +++ b/yarn-project/pxe/src/kernel_prover/hints_builder.ts @@ -84,7 +84,7 @@ export class HintsBuilder { async getNullifierMembershipWitness(nullifier: Fr) { const res = await this.oracle.getNullifierMembershipWitness(nullifier); if (!res) { - return; + throw new Error(`Cannot find the leaf for nullifier ${nullifier.toBigInt()}.`); } const { index, siblingPath, leafPreimage } = res; diff --git a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts index 0e0687f9bb7..1632ebc3164 100644 --- a/yarn-project/pxe/src/kernel_prover/kernel_prover.ts +++ b/yarn-project/pxe/src/kernel_prover/kernel_prover.ts @@ -1,11 +1,13 @@ import { CallRequest, Fr, + type MAX_ENCRYPTED_LOGS_PER_TX, type MAX_NEW_NOTE_HASHES_PER_TX, type MAX_NEW_NULLIFIERS_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, MAX_PRIVATE_CALL_STACK_LENGTH_PER_CALL, MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, + type MAX_UNENCRYPTED_LOGS_PER_TX, NoteHashReadRequestMembershipWitness, PrivateCallData, PrivateKernelCircuitPublicInputs, @@ -162,11 +164,20 @@ export class KernelProver { typeof MAX_NEW_NULLIFIERS_PER_TX >(output.publicInputs.end.newNullifiers); + const [sortedEncryptedLogHashes, sortedEncryptedLogHashesIndexes] = this.hintsBuilder.sortSideEffects< + SideEffect, + typeof MAX_ENCRYPTED_LOGS_PER_TX + >(output.publicInputs.end.encryptedLogsHashes); + + const [sortedUnencryptedLogHashes, sortedUnencryptedLogHashesIndexes] = this.hintsBuilder.sortSideEffects< + SideEffect, + typeof MAX_UNENCRYPTED_LOGS_PER_TX + >(output.publicInputs.end.unencryptedLogsHashes); + const nullifierNoteHashHints = this.hintsBuilder.getNullifierHints( mapTuple(sortedNullifiers, n => n.noteHash), sortedNoteHashes, ); - this.log.debug( `Calling private kernel tail with hwm ${previousKernelData.publicInputs.minRevertibleSideEffectCounter}`, ); @@ -180,6 +191,10 @@ export class KernelProver { sortedNullifiersIndexes, nullifierReadRequestHints, nullifierNoteHashHints, + sortedEncryptedLogHashes, + sortedEncryptedLogHashesIndexes, + sortedUnencryptedLogHashes, + sortedUnencryptedLogHashesIndexes, masterNullifierSecretKeys, ); pushTestData('private-kernel-inputs-ordering', privateInputs); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 45f0a9eb16e..9f1d341533d 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -1,6 +1,8 @@ import { type AuthWitness, type AztecNode, + EncryptedFunctionL2Logs, + type EncryptedL2Log, EncryptedTxL2Logs, ExtendedNote, type FunctionCall, @@ -18,6 +20,8 @@ import { type TxExecutionRequest, type TxHash, type TxReceipt, + UnencryptedFunctionL2Logs, + type UnencryptedL2Log, UnencryptedTxL2Logs, isNoirCallStackUnresolved, } from '@aztec/circuit-types'; @@ -32,6 +36,7 @@ import { type PartialAddress, type PrivateKernelTailCircuitPublicInputs, type PublicCallRequest, + type SideEffect, computeContractClassId, getContractClassFromArtifact, } from '@aztec/circuits.js'; @@ -417,8 +422,7 @@ export class PXEService implements PXE { } if (simulatePublic) { - // Only one transaction, so we can take index 0. - simulatedTx.publicReturnValues = (await this.#simulatePublicCalls(simulatedTx.tx))[0]; + simulatedTx.publicReturnValues = await this.#simulatePublicCalls(simulatedTx.tx); } if (!msgSender) { @@ -637,8 +641,7 @@ export class PXEService implements PXE { this.log.debug(`Executing kernel prover...`); const { proof, publicInputs } = await kernelProver.prove(txExecutionRequest.toTxRequest(), executionResult); - const encryptedLogs = new EncryptedTxL2Logs(collectEncryptedLogs(executionResult)); - const unencryptedLogs = new UnencryptedTxL2Logs(collectUnencryptedLogs(executionResult)); + const { encryptedLogs, unencryptedLogs } = this.patchLogsOrdering(executionResult); const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(executionResult); // HACK(#1639): Manually patches the ordering of the public call stack @@ -646,7 +649,7 @@ export class PXEService implements PXE { await this.patchPublicCallStackOrdering(publicInputs, enqueuedPublicFunctions); const tx = new Tx(publicInputs, proof, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions); - return new SimulatedTx(tx, [executionResult.returnValues]); + return new SimulatedTx(tx, executionResult.returnValues); } /** @@ -756,6 +759,61 @@ export class PXEService implements PXE { ); } + // As above, this is a hack for encrypted/unencrypted logs ordering, now they are sorted. Since the private kernel + // cannot keep track of side effects that happen after or before a nested call, we override the gathered logs. + // As a sanity check, we at least verify that the elements are the same, so we are only tweaking their ordering. + // See yarn-project/end-to-end/src/e2e_ordering.test.ts + // See https://github.com/AztecProtocol/aztec-packages/issues/1641 + // Added as part of resolving #5017 + private patchLogsOrdering(execResult: ExecutionResult) { + const encLogs = collectEncryptedLogs(execResult).flatMap(l => l.logs); + const unencLogs = collectUnencryptedLogs(execResult).flatMap(l => l.logs); + const getLogs = (res: ExecutionResult, enc: boolean) => { + const logs: SideEffect[] = enc + ? res.callStackItem.publicInputs.encryptedLogsHashes.concat(res.nestedExecutions.flatMap(e => getLogs(e, true))) + : res.callStackItem.publicInputs.unencryptedLogsHashes.concat( + res.nestedExecutions.flatMap(e => getLogs(e, false)), + ); + + return logs; + }; + + const sortSEs = (a: SideEffect, b: SideEffect) => { + if (a.isEmpty()) { + return 1; + } else if (b.isEmpty()) { + return -1; + } else { + return Number(a.counter.toBigInt() - b.counter.toBigInt()); + } + }; + + const sortedEncLogs = getLogs(execResult, true).sort(sortSEs); + const sortedUnencLogs = getLogs(execResult, false).sort(sortSEs); + + const finalEncLogs: EncryptedL2Log[] = []; + sortedEncLogs.forEach((sideEffect: SideEffect) => { + if (!sideEffect.isEmpty()) { + const isLog = (log: EncryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value); + const thisLogIndex = encLogs.findIndex(isLog); + finalEncLogs.push(encLogs[thisLogIndex]); + } + }); + + const finalUnencLogs: UnencryptedL2Log[] = []; + sortedUnencLogs.forEach((sideEffect: SideEffect) => { + if (!sideEffect.isEmpty()) { + const isLog = (log: UnencryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value); + const thisLogIndex = unencLogs.findIndex(isLog); + finalUnencLogs.push(unencLogs[thisLogIndex]); + } + }); + + const encryptedLogs = new EncryptedTxL2Logs([new EncryptedFunctionL2Logs(finalEncLogs)]); + const unencryptedLogs = new UnencryptedTxL2Logs([new UnencryptedFunctionL2Logs(finalUnencLogs)]); + return { encryptedLogs, unencryptedLogs }; + } + public async isGlobalStateSynchronized() { return await this.synchronizer.isGlobalStateSynchronized(); } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 56e65ee0e81..d5ba6c1a032 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -159,6 +159,11 @@ export class SimulatorOracle implements DBOracle { return new MessageLoadOracleInputs(messageIndex, siblingPath); } + // Only used in public. + public getL1ToL2LeafValue(_leafIndex: bigint): Promise { + throw new Error('Unimplemented in private!'); + } + /** * Gets the index of a commitment in the note hash tree. * @param commitment - The commitment. diff --git a/yarn-project/simulator/src/acvm/oracle/oracle.ts b/yarn-project/simulator/src/acvm/oracle/oracle.ts index c9223ae8f1d..fb3b35f028c 100644 --- a/yarn-project/simulator/src/acvm/oracle/oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/oracle.ts @@ -21,8 +21,13 @@ export class Oracle { return toACVMField(val); } - async packArguments(args: ACVMField[]): Promise { - const packed = await this.typedOracle.packArguments(args.map(fromACVMField)); + async packArgumentsArray(args: ACVMField[]): Promise { + const packed = await this.typedOracle.packArgumentsArray(args.map(fromACVMField)); + return toACVMField(packed); + } + + async packArguments(_length: ACVMField[], values: ACVMField[]): Promise { + const packed = await this.typedOracle.packArgumentsArray(values.map(fromACVMField)); return toACVMField(packed); } @@ -291,14 +296,14 @@ export class Oracle { log: ACVMField[], ): ACVMField { const publicKey = new Point(fromACVMField(publicKeyX), fromACVMField(publicKeyY)); - this.typedOracle.emitEncryptedLog( + const logHash = this.typedOracle.emitEncryptedLog( AztecAddress.fromString(contractAddress), Fr.fromString(storageSlot), Fr.fromString(noteTypeId), publicKey, log.map(fromACVMField), ); - return toACVMField(0); + return toACVMField(logHash); } emitUnencryptedLog([contractAddress]: ACVMField[], [eventSelector]: ACVMField[], message: ACVMField[]): ACVMField { @@ -309,8 +314,8 @@ export class Oracle { logPayload, ); - this.typedOracle.emitUnencryptedLog(log); - return toACVMField(0); + const logHash = this.typedOracle.emitUnencryptedLog(log); + return toACVMField(logHash); } debugLog(...args: ACVMField[][]): ACVMField { diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index 4f245732275..c362a04f8be 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -85,8 +85,8 @@ export abstract class TypedOracle { return Fr.random(); } - packArguments(_args: Fr[]): Promise { - throw new OracleMethodNotAvailableError('packArguments'); + packArgumentsArray(_args: Fr[]): Promise { + throw new OracleMethodNotAvailableError('packArgumentsArray'); } packReturns(_returns: Fr[]): Promise { @@ -205,11 +205,11 @@ export abstract class TypedOracle { _noteTypeId: Fr, _publicKey: PublicKey, _log: Fr[], - ): void { + ): Fr { throw new OracleMethodNotAvailableError('emitEncryptedLog'); } - emitUnencryptedLog(_log: UnencryptedL2Log): void { + emitUnencryptedLog(_log: UnencryptedL2Log): Fr { throw new OracleMethodNotAvailableError('emitUnencryptedLog'); } diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 051c3432de3..411d6c8fa84 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -20,7 +20,6 @@ import { initContext, initExecutionEnvironment, initGlobalVariables, - initL1ToL2MessageOracleInput, initMachineState, randomMemoryBytes, randomMemoryFields, @@ -136,23 +135,11 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); describe.each([ - [ - 'sha256_hash', - /*input=*/ randomMemoryBytes(10), - /*output=*/ (bytes: Uint8[]) => [...sha256(Buffer.concat(bytes.map(b => b.toBuffer())))].map(b => new Fr(b)), - ], - [ - 'keccak_hash', - /*input=*/ randomMemoryBytes(10), - /*output=*/ (bytes: Uint8[]) => [...keccak256(Buffer.concat(bytes.map(b => b.toBuffer())))].map(b => new Fr(b)), - ], - ['poseidon2_hash', /*input=*/ randomMemoryFields(10), /*output=*/ (fields: Fieldable[]) => [poseidon2Hash(fields)]], - ['pedersen_hash', /*input=*/ randomMemoryFields(10), /*output=*/ (fields: Fieldable[]) => [pedersenHash(fields)]], - [ - 'pedersen_hash_with_index', - /*input=*/ randomMemoryFields(10), - /*output=*/ (fields: Fieldable[]) => [pedersenHash(fields, /*index=*/ 20)], - ], + ['sha256_hash', /*input=*/ randomMemoryBytes(10), /*output=*/ sha256FromMemoryBytes], + ['keccak_hash', /*input=*/ randomMemoryBytes(10), /*output=*/ keccak256FromMemoryBytes], + ['poseidon2_hash', /*input=*/ randomMemoryFields(10), /*output=*/ poseidon2FromMemoryFields], + ['pedersen_hash', /*input=*/ randomMemoryFields(10), /*output=*/ pedersenFromMemoryFields], + ['pedersen_hash_with_index', /*input=*/ randomMemoryFields(10), /*output=*/ indexedPedersenFromMemoryFields], ])('Hashes in noir contracts', (name: string, input: MemoryValue[], output: (msg: any[]) => Fr[]) => { it(`Should execute contract function that performs ${name}`, async () => { const calldata = input.map(e => e.toFr()); @@ -496,9 +483,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { const calldata = [msgHash, leafIndex]; const context = initContext({ env: initExecutionEnvironment({ calldata }) }); - jest - .spyOn(context.persistableState.hostStorage.commitmentsDb, 'getL1ToL2MembershipWitness') - .mockResolvedValue(initL1ToL2MessageOracleInput(leafIndex.toBigInt())); + jest.spyOn(context.persistableState.hostStorage.commitmentsDb, 'getL1ToL2LeafValue').mockResolvedValue(msgHash); const bytecode = getAvmTestContractBytecode('l1_to_l2_msg_exists'); const results = await new AvmSimulator(context).executeBytecode(bytecode); @@ -929,3 +914,23 @@ function getAvmNestedCallsTestContractBytecode(functionName: string): Buffer { ); return artifact.bytecode; } + +function sha256FromMemoryBytes(bytes: Uint8[]): Fr[] { + return [...sha256(Buffer.concat(bytes.map(b => b.toBuffer())))].map(b => new Fr(b)); +} + +function keccak256FromMemoryBytes(bytes: Uint8[]): Fr[] { + return [...keccak256(Buffer.concat(bytes.map(b => b.toBuffer())))].map(b => new Fr(b)); +} + +function poseidon2FromMemoryFields(fields: Fieldable[]): Fr[] { + return [poseidon2Hash(fields)]; +} + +function pedersenFromMemoryFields(fields: Fieldable[]): Fr[] { + return [pedersenHash(fields)]; +} + +function indexedPedersenFromMemoryFields(fields: Fieldable[]): Fr[] { + return [pedersenHash(fields, /*index=*/ 20)]; +} diff --git a/yarn-project/simulator/src/avm/fixtures/index.ts b/yarn-project/simulator/src/avm/fixtures/index.ts index c03fa818166..ef9233bb686 100644 --- a/yarn-project/simulator/src/avm/fixtures/index.ts +++ b/yarn-project/simulator/src/avm/fixtures/index.ts @@ -1,5 +1,4 @@ -import { SiblingPath } from '@aztec/circuit-types'; -import { GasFees, GasSettings, GlobalVariables, Header, L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js'; +import { GasFees, GasSettings, GlobalVariables, Header } from '@aztec/circuits.js'; import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { EthAddress } from '@aztec/foundation/eth-address'; @@ -8,12 +7,7 @@ import { Fr } from '@aztec/foundation/fields'; import { mock } from 'jest-mock-extended'; import merge from 'lodash.merge'; -import { - type CommitmentsDB, - MessageLoadOracleInputs, - type PublicContractsDB, - type PublicStateDB, -} from '../../index.js'; +import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from '../../index.js'; import { AvmContext } from '../avm_context.js'; import { AvmContextInputs, AvmExecutionEnvironment } from '../avm_execution_environment.js'; import { AvmMachineState } from '../avm_machine_state.js'; @@ -111,18 +105,6 @@ export function allSameExcept(original: any, overrides: any): any { return merge({}, original, overrides); } -/** - * Create an empty L1ToL2Message oracle input - */ -export function initL1ToL2MessageOracleInput( - leafIndex?: bigint, -): MessageLoadOracleInputs { - return new MessageLoadOracleInputs( - leafIndex ?? 0n, - new SiblingPath(L1_TO_L2_MSG_TREE_HEIGHT, Array(L1_TO_L2_MSG_TREE_HEIGHT)), - ); -} - /** * Adjust the user index to account for the AvmContextInputs size. * This is a hack for testing, and should go away once AvmContextInputs themselves go away. diff --git a/yarn-project/simulator/src/avm/journal/journal.test.ts b/yarn-project/simulator/src/avm/journal/journal.test.ts index 400d7066921..8a42f1e6796 100644 --- a/yarn-project/simulator/src/avm/journal/journal.test.ts +++ b/yarn-project/simulator/src/avm/journal/journal.test.ts @@ -6,7 +6,6 @@ import { Fr } from '@aztec/foundation/fields'; import { type MockProxy, mock } from 'jest-mock-extended'; import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from '../../index.js'; -import { initL1ToL2MessageOracleInput } from '../fixtures/index.js'; import { HostStorage } from './host_storage.js'; import { AvmPersistableStateManager, type JournalData } from './journal.js'; @@ -114,28 +113,28 @@ describe('journal', () => { ]); }); it('checkL1ToL2MessageExists works for missing message', async () => { - const utxo = new Fr(2); + const msgHash = new Fr(2); const leafIndex = new Fr(42); - const exists = await journal.checkL1ToL2MessageExists(utxo, leafIndex); + const exists = await journal.checkL1ToL2MessageExists(msgHash, leafIndex); expect(exists).toEqual(false); const journalUpdates = journal.flush(); expect(journalUpdates.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: leafIndex, msgHash: utxo, exists: false }), + expect.objectContaining({ leafIndex: leafIndex, msgHash, exists: false }), ]); }); - it('checkL1ToL2MessageExists works for existing nullifiers', async () => { - const utxo = new Fr(2); + it('checkL1ToL2MessageExists works for existing msgHash', async () => { + const msgHash = new Fr(2); const leafIndex = new Fr(42); - commitmentsDb.getL1ToL2MembershipWitness.mockResolvedValue(initL1ToL2MessageOracleInput(leafIndex.toBigInt())); - const exists = await journal.checkL1ToL2MessageExists(utxo, leafIndex); + commitmentsDb.getL1ToL2LeafValue.mockResolvedValue(msgHash); + const exists = await journal.checkL1ToL2MessageExists(msgHash, leafIndex); expect(exists).toEqual(true); const journalUpdates = journal.flush(); expect(journalUpdates.l1ToL2MessageChecks).toEqual([ - expect.objectContaining({ leafIndex: leafIndex, msgHash: utxo, exists: true }), + expect.objectContaining({ leafIndex: leafIndex, msgHash, exists: true }), ]); }); it('Should maintain nullifiers', async () => { @@ -150,11 +149,11 @@ describe('journal', () => { }); it('Should maintain l1 messages', () => { const recipient = EthAddress.fromField(new Fr(1)); - const utxo = new Fr(2); - journal.writeL1Message(recipient, utxo); + const msgHash = new Fr(2); + journal.writeL1Message(recipient, msgHash); const journalUpdates = journal.flush(); - expect(journalUpdates.newL1Messages).toEqual([{ recipient, content: utxo }]); + expect(journalUpdates.newL1Messages).toEqual([{ recipient, content: msgHash }]); }); }); diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 5972aeb391e..5c21dd175a3 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -16,6 +16,7 @@ import { type TracedNullifierCheck, type TracedPublicStorageRead, type TracedPublicStorageWrite, + type TracedUnencryptedL2Log, } from './trace_types.js'; /** @@ -33,7 +34,7 @@ export type JournalData = { newL1Messages: L2ToL1Message[]; newLogs: UnencryptedL2Log[]; - + newLogsHashes: TracedUnencryptedL2Log[]; /** contract address -\> key -\> value */ currentStorageValue: Map>; }; @@ -171,24 +172,11 @@ export class AvmPersistableStateManager { * @returns exists - whether the message exists in the L1 to L2 Messages tree */ public async checkL1ToL2MessageExists(msgHash: Fr, msgLeafIndex: Fr): Promise { - let exists = false; - try { - // The following 2 values are used to compute a message nullifier. Given that here we do not care about getting - // non-nullified messages we can just pass in random values and the nullifier check will effectively be ignored - // (no nullifier will be found). - const ignoredContractAddress = AztecAddress.random(); - const ignoredSecret = Fr.random(); - const gotMessage = await this.hostStorage.commitmentsDb.getL1ToL2MembershipWitness( - ignoredContractAddress, - msgHash, - ignoredSecret, - ); - exists = gotMessage !== undefined && gotMessage.index == msgLeafIndex.toBigInt(); - } catch { - // error getting message - doesn't exist! - exists = false; - } - this.log.debug(`l1ToL2Messages(${msgHash})@${msgLeafIndex} ?? exists: ${exists}.`); + const valueAtIndex = await this.hostStorage.commitmentsDb.getL1ToL2LeafValue(msgLeafIndex.toBigInt()); + const exists = valueAtIndex?.equals(msgHash) ?? false; + this.log.debug( + `l1ToL2Messages(@${msgLeafIndex}) ?? exists: ${exists}, expected: ${msgHash}, found: ${valueAtIndex}.`, + ); this.trace.traceL1ToL2MessageCheck(msgHash, msgLeafIndex, exists); return Promise.resolve(exists); } @@ -206,13 +194,13 @@ export class AvmPersistableStateManager { public writeLog(contractAddress: Fr, event: Fr, log: Fr[]) { this.log.debug(`UnencryptedL2Log(${contractAddress}) += event ${event} with ${log.length} fields.`); - this.newLogs.push( - new UnencryptedL2Log( - AztecAddress.fromField(contractAddress), - EventSelector.fromField(event), - Buffer.concat(log.map(f => f.toBuffer())), - ), + const L2log = new UnencryptedL2Log( + AztecAddress.fromField(contractAddress), + EventSelector.fromField(event), + Buffer.concat(log.map(f => f.toBuffer())), ); + this.newLogs.push(L2log); + this.trace.traceNewLog(Fr.fromBuffer(L2log.hash())); } /** @@ -252,6 +240,7 @@ export class AvmPersistableStateManager { l1ToL2MessageChecks: this.trace.l1ToL2MessageChecks, newL1Messages: this.newL1Messages, newLogs: this.newLogs, + newLogsHashes: this.trace.newLogsHashes, currentStorageValue: this.publicStorage.getCache().cachePerContract, storageReads: this.trace.publicStorageReads, storageWrites: this.trace.publicStorageWrites, diff --git a/yarn-project/simulator/src/avm/journal/trace.ts b/yarn-project/simulator/src/avm/journal/trace.ts index aa88454f9b7..8cb115eae67 100644 --- a/yarn-project/simulator/src/avm/journal/trace.ts +++ b/yarn-project/simulator/src/avm/journal/trace.ts @@ -8,6 +8,7 @@ import { type TracedNullifierCheck, type TracedPublicStorageRead, type TracedPublicStorageWrite, + type TracedUnencryptedL2Log, } from './trace_types.js'; export class WorldStateAccessTrace { @@ -21,6 +22,7 @@ export class WorldStateAccessTrace { public nullifierChecks: TracedNullifierCheck[] = []; public newNullifiers: TracedNullifier[] = []; public l1ToL2MessageChecks: TracedL1toL2MessageCheck[] = []; + public newLogsHashes: TracedUnencryptedL2Log[] = []; //public contractCalls: TracedContractCall[] = []; //public archiveChecks: TracedArchiveLeafCheck[] = []; @@ -133,6 +135,15 @@ export class WorldStateAccessTrace { this.incrementAccessCounter(); } + public traceNewLog(logHash: Fr) { + const traced: TracedUnencryptedL2Log = { + logHash, + counter: new Fr(this.accessCounter), + }; + this.newLogsHashes.push(traced); + this.incrementAccessCounter(); + } + private incrementAccessCounter() { this.accessCounter++; } @@ -155,6 +166,7 @@ export class WorldStateAccessTrace { this.nullifierChecks = this.nullifierChecks.concat(incomingTrace.nullifierChecks); this.newNullifiers = this.newNullifiers.concat(incomingTrace.newNullifiers); this.l1ToL2MessageChecks = this.l1ToL2MessageChecks.concat(incomingTrace.l1ToL2MessageChecks); + this.newLogsHashes = this.newLogsHashes.concat(incomingTrace.newLogsHashes); // it is assumed that the incoming trace was initialized with this as parent, so accept counter this.accessCounter = incomingTrace.accessCounter; } diff --git a/yarn-project/simulator/src/avm/journal/trace_types.ts b/yarn-project/simulator/src/avm/journal/trace_types.ts index 81de24729e7..3c93649cefd 100644 --- a/yarn-project/simulator/src/avm/journal/trace_types.ts +++ b/yarn-project/simulator/src/avm/journal/trace_types.ts @@ -73,6 +73,13 @@ export type TracedL1toL2MessageCheck = { //endLifetime: Fr; }; +export type TracedUnencryptedL2Log = { + //callPointer: Fr; + logHash: Fr; + counter: Fr; + //endLifetime: Fr; +}; + //export type TracedArchiveLeafCheck = { // leafIndex: Fr; // leaf: Fr; diff --git a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts index 5eac2f364f4..88c7cadd138 100644 --- a/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/accrued_substate.test.ts @@ -8,12 +8,7 @@ import { type CommitmentsDB } from '../../index.js'; import { type AvmContext } from '../avm_context.js'; import { Field, Uint8 } from '../avm_memory_types.js'; import { InstructionExecutionError } from '../errors.js'; -import { - initContext, - initExecutionEnvironment, - initHostStorage, - initL1ToL2MessageOracleInput, -} from '../fixtures/index.js'; +import { initContext, initExecutionEnvironment, initHostStorage } from '../fixtures/index.js'; import { AvmPersistableStateManager } from '../journal/journal.js'; import { EmitNoteHash, @@ -348,7 +343,7 @@ describe('Accrued Substate', () => { // mock commitments db to show message exists const commitmentsDb = mock(); - commitmentsDb.getL1ToL2MembershipWitness.mockResolvedValue(initL1ToL2MessageOracleInput(leafIndex.toBigInt())); + commitmentsDb.getL1ToL2LeafValue.mockResolvedValue(msgHash.toFr()); const hostStorage = initHostStorage({ commitmentsDb }); context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); @@ -356,7 +351,6 @@ describe('Accrued Substate', () => { context.machineState.memory.set(msgLeafIndexOffset, leafIndex); await new L1ToL2MessageExists(/*indirect=*/ 0, msgHashOffset, msgLeafIndexOffset, existsOffset).execute(context); - // never created, doesn't exist! const exists = context.machineState.memory.getAs(existsOffset); expect(exists).toEqual(new Uint8(1)); @@ -365,6 +359,32 @@ describe('Accrued Substate', () => { expect.objectContaining({ leafIndex: leafIndex.toFr(), msgHash: msgHash.toFr(), exists: true }), ]); }); + + it('Should correctly show false when another L1ToL2 message exists at that index', async () => { + const msgHash = new Field(69n); + const leafIndex = new Field(42n); + const msgHashOffset = 0; + const msgLeafIndexOffset = 1; + const existsOffset = 2; + + const commitmentsDb = mock(); + commitmentsDb.getL1ToL2LeafValue.mockResolvedValue(Fr.ZERO); + const hostStorage = initHostStorage({ commitmentsDb }); + context = initContext({ persistableState: new AvmPersistableStateManager(hostStorage) }); + + context.machineState.memory.set(msgHashOffset, msgHash); + context.machineState.memory.set(msgLeafIndexOffset, leafIndex); + await new L1ToL2MessageExists(/*indirect=*/ 0, msgHashOffset, msgLeafIndexOffset, existsOffset).execute(context); + + // never created, doesn't exist! + const exists = context.machineState.memory.getAs(existsOffset); + expect(exists).toEqual(new Uint8(0)); + + const journalState = context.persistableState.flush(); + expect(journalState.l1ToL2MessageChecks).toEqual([ + expect.objectContaining({ leafIndex: leafIndex.toFr(), msgHash: msgHash.toFr(), exists: false }), + ]); + }); }); describe('EmitUnencryptedLog', () => { diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index 0c045247407..5d7d33375b4 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -171,10 +171,10 @@ export class ClientExecutionContext extends ViewDataOracle { } /** - * Pack the given arguments. + * Pack the given array of arguments. * @param args - Arguments to pack */ - public override packArguments(args: Fr[]): Promise { + public override packArgumentsArray(args: Fr[]): Promise { return Promise.resolve(this.packedValuesCache.pack(args)); } @@ -328,7 +328,9 @@ export class ClientExecutionContext extends ViewDataOracle { const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId); const taggedNote = new TaggedNote(l1NotePayload); const encryptedNote = taggedNote.toEncryptedBuffer(publicKey, this.curve); - this.encryptedLogs.push(new EncryptedL2Log(encryptedNote)); + const encryptedLog = new EncryptedL2Log(encryptedNote); + this.encryptedLogs.push(encryptedLog); + return Fr.fromBuffer(encryptedLog.hash()); } /** @@ -339,6 +341,7 @@ export class ClientExecutionContext extends ViewDataOracle { this.unencryptedLogs.push(log); const text = log.toHumanReadable(); this.log.verbose(`Emitted unencrypted log: "${text.length > 100 ? text.slice(0, 100) + '...' : text}"`); + return Fr.fromBuffer(log.hash()); } #checkValidStaticCall(childExecutionResult: ExecutionResult) { diff --git a/yarn-project/simulator/src/client/execution_result.ts b/yarn-project/simulator/src/client/execution_result.ts index 5118b28d607..845386e9807 100644 --- a/yarn-project/simulator/src/client/execution_result.ts +++ b/yarn-project/simulator/src/client/execution_result.ts @@ -4,7 +4,6 @@ import { type PrivateCallStackItem, type PublicCallRequest, } from '@aztec/circuits.js'; -import { type DecodedReturn } from '@aztec/foundation/abi'; import { type Fr } from '@aztec/foundation/fields'; import { type ACVMField } from '../acvm/index.js'; @@ -40,20 +39,20 @@ export interface ExecutionResult { // Needed when we enable chained txs. The new notes can be cached and used in a later transaction. /** The notes created in the executed function. */ newNotes: NoteAndSlot[]; - /** The decoded return values of the executed function. */ - returnValues: DecodedReturn; + /** The raw return values of the executed function. */ + returnValues: Fr[]; /** The nested executions. */ nestedExecutions: this[]; /** Enqueued public function execution requests to be picked up by the sequencer. */ enqueuedPublicFunctionCalls: PublicCallRequest[]; /** * Encrypted logs emitted during execution of this function call. - * Note: These are preimages to `encryptedLogsHash`. + * Note: These are preimages to `encryptedLogsHashes`. */ encryptedLogs: EncryptedFunctionL2Logs; /** * Unencrypted logs emitted during execution of this function call. - * Note: These are preimages to `unencryptedLogsHash`. + * Note: These are preimages to `unencryptedLogsHashes`. */ unencryptedLogs: UnencryptedFunctionL2Logs; } diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index b3bdc01968b..512060e9948 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -433,7 +433,7 @@ describe('Private Execution test suite', () => { const artifact = getFunctionArtifact(ChildContractArtifact, 'value'); const result = await runSimulator({ args: [initialValue], artifact }); - expect(result.returnValues).toEqual([initialValue + privateIncrement]); + expect(result.returnValues).toEqual([new Fr(initialValue + privateIncrement)]); }); it('parent should call child', async () => { @@ -452,12 +452,12 @@ describe('Private Execution test suite', () => { const args = [childAddress, childSelector]; const result = await runSimulator({ args, artifact: parentArtifact }); - expect(result.returnValues).toEqual([privateIncrement]); + expect(result.returnValues).toEqual([new Fr(privateIncrement)]); expect(oracle.getFunctionArtifact.mock.calls[0]).toEqual([childAddress, childSelector]); expect(oracle.getPortalContractAddress.mock.calls[0]).toEqual([childAddress]); expect(result.nestedExecutions).toHaveLength(1); - expect(result.nestedExecutions[0].returnValues).toEqual([privateIncrement]); + expect(result.nestedExecutions[0].returnValues).toEqual([new Fr(privateIncrement)]); // check that Aztec.nr calculated the call stack item hash like cpp does const expectedCallStackItemHash = result.nestedExecutions[0].callStackItem.hash(); @@ -486,12 +486,12 @@ describe('Private Execution test suite', () => { logger.info(`Calling testCodeGen function`); const result = await runSimulator({ args, artifact: testCodeGenArtifact }); - expect(result.returnValues).toEqual([argsHash.toBigInt()]); + expect(result.returnValues).toEqual([argsHash]); }); it('test function should be callable through autogenerated interface', async () => { const testAddress = AztecAddress.random(); - const parentArtifact = getFunctionArtifact(ImportTestContractArtifact, 'main'); + const parentArtifact = getFunctionArtifact(ImportTestContractArtifact, 'main_contract'); const testCodeGenSelector = FunctionSelector.fromNameAndParameters( testCodeGenArtifact.name, testCodeGenArtifact.parameters, @@ -504,11 +504,11 @@ describe('Private Execution test suite', () => { const args = [testAddress]; const result = await runSimulator({ args, artifact: parentArtifact }); - expect(result.returnValues).toEqual([argsHash.toBigInt()]); + expect(result.returnValues).toEqual([argsHash]); expect(oracle.getFunctionArtifact.mock.calls[0]).toEqual([testAddress, testCodeGenSelector]); expect(oracle.getPortalContractAddress.mock.calls[0]).toEqual([testAddress]); expect(result.nestedExecutions).toHaveLength(1); - expect(result.nestedExecutions[0].returnValues).toEqual([argsHash.toBigInt()]); + expect(result.nestedExecutions[0].returnValues).toEqual([argsHash]); }); }); @@ -899,7 +899,7 @@ describe('Private Execution test suite', () => { const readRequest = sideEffectArrayToValueArray(result.callStackItem.publicInputs.noteHashReadRequests)[0]; expect(readRequest).toEqual(innerNoteHash); - expect(result.returnValues).toEqual([amountToTransfer]); + expect(result.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = result.callStackItem.publicInputs.newNullifiers[0]; const siloedNullifierSecretKey = computeSiloedNullifierSecretKey( @@ -974,7 +974,7 @@ describe('Private Execution test suite', () => { const readRequest = execGetThenNullify.callStackItem.publicInputs.noteHashReadRequests[0]; expect(readRequest.value).toEqual(innerNoteHash); - expect(execGetThenNullify.returnValues).toEqual([amountToTransfer]); + expect(execGetThenNullify.returnValues).toEqual([new Fr(amountToTransfer)]); const nullifier = execGetThenNullify.callStackItem.publicInputs.newNullifiers[0]; const siloedNullifierSecretKey = computeSiloedNullifierSecretKey( @@ -1013,7 +1013,6 @@ describe('Private Execution test suite', () => { it('gets the public key for an address', async () => { // Tweak the contract artifact so we can extract return values const artifact = getFunctionArtifact(TestContractArtifact, 'get_public_key'); - artifact.returnTypes = [{ kind: 'array', length: 2, type: { kind: 'field' } }]; // Generate a partial address, pubkey, and resulting address const completeAddress = CompleteAddress.random(); @@ -1022,7 +1021,7 @@ describe('Private Execution test suite', () => { oracle.getCompleteAddress.mockResolvedValue(completeAddress); const result = await runSimulator({ artifact, args }); - expect(result.returnValues).toEqual([pubKey.x.toBigInt(), pubKey.y.toBigInt()]); + expect(result.returnValues).toEqual([pubKey.x, pubKey.y]); }); }); @@ -1046,14 +1045,13 @@ describe('Private Execution test suite', () => { // Tweak the contract artifact so we can extract return values const artifact = getFunctionArtifact(TestContractArtifact, 'get_portal_contract_address'); - artifact.returnTypes = [{ kind: 'field' }]; const args = [aztecAddressToQuery.toField()]; // Overwrite the oracle return value oracle.getPortalContractAddress.mockResolvedValue(portalContractAddress); const result = await runSimulator({ artifact, args }); - expect(result.returnValues).toEqual([portalContractAddress.toField().value]); + expect(result.returnValues).toEqual([portalContractAddress.toField()]); }); it('this_address should return the current context address', async () => { @@ -1061,11 +1059,10 @@ describe('Private Execution test suite', () => { // Tweak the contract artifact so we can extract return values const artifact = getFunctionArtifact(TestContractArtifact, 'get_this_address'); - artifact.returnTypes = [{ kind: 'field' }]; // Overwrite the oracle return value const result = await runSimulator({ artifact, args: [], contractAddress }); - expect(result.returnValues).toEqual([contractAddress.toField().toBigInt()]); + expect(result.returnValues).toEqual([contractAddress.toField()]); }); it("this_portal_address should return the current context's portal address", async () => { @@ -1073,11 +1070,10 @@ describe('Private Execution test suite', () => { // Tweak the contract artifact so we can extract return values const artifact = getFunctionArtifact(TestContractArtifact, 'get_this_portal_address'); - artifact.returnTypes = [{ kind: 'field' }]; // Overwrite the oracle return value const result = await runSimulator({ artifact, args: [], portalContractAddress }); - expect(result.returnValues).toEqual([portalContractAddress.toField().toBigInt()]); + expect(result.returnValues).toEqual([portalContractAddress.toField()]); }); }); diff --git a/yarn-project/simulator/src/client/private_execution.ts b/yarn-project/simulator/src/client/private_execution.ts index 7a7b0d13288..64cf9baae7d 100644 --- a/yarn-project/simulator/src/client/private_execution.ts +++ b/yarn-project/simulator/src/client/private_execution.ts @@ -1,5 +1,5 @@ import { type FunctionData, PrivateCallStackItem, PrivateCircuitPublicInputs } from '@aztec/circuits.js'; -import { type AbiType, type FunctionArtifactWithDebugMetadata, decodeReturnValues } from '@aztec/foundation/abi'; +import { type FunctionArtifactWithDebugMetadata } from '@aztec/foundation/abi'; import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -46,19 +46,12 @@ export async function executePrivateFunction( const encryptedLogs = context.getEncryptedLogs(); const unencryptedLogs = context.getUnencryptedLogs(); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) --> set this in Noir - publicInputs.encryptedLogsHash = Fr.fromBuffer(encryptedLogs.hash()); publicInputs.encryptedLogPreimagesLength = new Fr(encryptedLogs.getSerializedLength()); - publicInputs.unencryptedLogsHash = Fr.fromBuffer(unencryptedLogs.hash()); publicInputs.unencryptedLogPreimagesLength = new Fr(unencryptedLogs.getSerializedLength()); const callStackItem = new PrivateCallStackItem(contractAddress, functionData, publicInputs); - // Mocking the return type to be an array of 4 fields - // TODO: @LHerskind must be updated as we are progressing with the macros to get the information const rawReturnValues = await context.unpackReturns(publicInputs.returnsHash); - const returnTypes: AbiType[] = [{ kind: 'array', length: rawReturnValues.length, type: { kind: 'field' } }]; - const mockArtifact = { ...artifact, returnTypes }; - const returnValues = decodeReturnValues(mockArtifact, rawReturnValues); const noteHashReadRequestPartialWitnesses = context.getNoteHashReadRequestPartialWitnesses( publicInputs.noteHashReadRequests, @@ -73,7 +66,7 @@ export async function executePrivateFunction( acir, partialWitness, callStackItem, - returnValues, + returnValues: rawReturnValues, noteHashReadRequestPartialWitnesses, newNotes, vk: Buffer.from(artifact.verificationKey!, 'hex'), diff --git a/yarn-project/simulator/src/mocks/fixtures.ts b/yarn-project/simulator/src/mocks/fixtures.ts index df43be16805..96d2c9cc39e 100644 --- a/yarn-project/simulator/src/mocks/fixtures.ts +++ b/yarn-project/simulator/src/mocks/fixtures.ts @@ -127,6 +127,7 @@ export class PublicExecutionResultBuilder { newNullifiers: [], newL2ToL1Messages: [], contractStorageReads: [], + unencryptedLogsHashes: [], unencryptedLogs: UnencryptedFunctionL2Logs.empty(), startSideEffectCounter: Fr.ZERO, endSideEffectCounter: Fr.ZERO, diff --git a/yarn-project/simulator/src/public/abstract_phase_manager.ts b/yarn-project/simulator/src/public/abstract_phase_manager.ts index cb56906ea2a..2f62dd004d4 100644 --- a/yarn-project/simulator/src/public/abstract_phase_manager.ts +++ b/yarn-project/simulator/src/public/abstract_phase_manager.ts @@ -1,5 +1,6 @@ import { MerkleTreeId, + type ProcessReturnValues, type PublicKernelRequest, type SimulationError, type Tx, @@ -26,6 +27,7 @@ import { MAX_PUBLIC_DATA_READS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_CALL, MembershipWitness, type PrivateKernelTailCircuitPublicInputs, type Proof, @@ -47,13 +49,6 @@ import { makeEmptyProof, } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; -import { - type AbiType, - type DecodedReturn, - type FunctionArtifact, - type ProcessReturnValues, - decodeReturnValues, -} from '@aztec/foundation/abi'; import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { type Tuple } from '@aztec/foundation/serialize'; @@ -236,13 +231,11 @@ export abstract class AbstractPhaseManager { // separate public callstacks to be proven by separate public kernel sequences // and submitted separately to the base rollup? - const returns = []; + let returns: ProcessReturnValues = undefined; for (const enqueuedCall of enqueuedCalls) { const executionStack: (PublicExecution | PublicExecutionResult)[] = [enqueuedCall]; - let currentReturn: DecodedReturn | undefined = undefined; - // Keep track of which result is for the top/enqueued call let enqueuedExecutionResult: PublicExecutionResult | undefined; @@ -301,21 +294,12 @@ export abstract class AbstractPhaseManager { if (!enqueuedExecutionResult) { enqueuedExecutionResult = result; - - // TODO(#5450) Need to use the proper return values here - const returnTypes: AbiType[] = [ - { kind: 'array', length: result.returnValues.length, type: { kind: 'field' } }, - ]; - const mockArtifact = { returnTypes } as any as FunctionArtifact; - - currentReturn = decodeReturnValues(mockArtifact, result.returnValues); + returns = result.returnValues; } } // HACK(#1622): Manually patches the ordering of public state actions // TODO(#757): Enforce proper ordering of public state actions patchPublicStorageActionOrdering(kernelOutput, enqueuedExecutionResult!, this.phase); - - returns.push(currentReturn); } // TODO(#3675): This should be done in a public kernel circuit @@ -375,8 +359,6 @@ export abstract class AbstractPhaseManager { MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL, ); - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1165) --> set this in Noir - const unencryptedLogsHash = Fr.fromBuffer(result.unencryptedLogs.hash()); const unencryptedLogPreimagesLength = new Fr(result.unencryptedLogs.getSerializedLength()); return PublicCircuitPublicInputs.from({ @@ -410,7 +392,11 @@ export abstract class AbstractPhaseManager { MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, ), publicCallStackHashes, - unencryptedLogsHash, + unencryptedLogsHashes: padArrayEnd( + result.unencryptedLogsHashes, + SideEffect.empty(), + MAX_UNENCRYPTED_LOGS_PER_CALL, + ), unencryptedLogPreimagesLength, historicalHeader: this.historicalHeader, // TODO(@just-mitch): need better mapping from simulator to revert code. @@ -518,29 +504,9 @@ function patchPublicStorageActionOrdering( // so the returned result will be a subset of the public kernel output. const simPublicDataReads = collectPublicDataReads(execResult); - // verify that each read is in the kernel output - for (const read of simPublicDataReads) { - if (!publicDataReads.find(item => item.equals(read))) { - throw new Error( - `Public data reads from simulator do not match those from public kernel.\nFrom simulator: ${simPublicDataReads - .map(p => p.toFriendlyJSON()) - .join(', ')}\nFrom public kernel: ${publicDataReads.map(i => i.toFriendlyJSON()).join(', ')}`, - ); - } - } const simPublicDataUpdateRequests = collectPublicDataUpdateRequests(execResult); - for (const update of simPublicDataUpdateRequests) { - if (!publicDataUpdateRequests.find(item => item.equals(update))) { - throw new Error( - `Public data update requests from simulator do not match those from public kernel.\nFrom simulator: ${simPublicDataUpdateRequests - .map(p => p.toFriendlyJSON()) - .join(', ')}\nFrom public kernel revertible: ${publicDataUpdateRequests - .map(i => i.toFriendlyJSON()) - .join(', ')}`, - ); - } - } + // We only want to reorder the items from the public inputs of the // most recently processed top/enqueued call. diff --git a/yarn-project/simulator/src/public/avm_executor.test.ts b/yarn-project/simulator/src/public/avm_executor.test.ts index d0c0fc234dc..43c1dc7663c 100644 --- a/yarn-project/simulator/src/public/avm_executor.test.ts +++ b/yarn-project/simulator/src/public/avm_executor.test.ts @@ -72,6 +72,6 @@ describe('AVM WitGen and Proof Generation', () => { const valid = await executor.verifyAvmProof(vk, proof); expect(valid).toBe(true); }, - 60 * 1000, - ); // 60 seconds should be enough to generate the proof with 16-bit range checks + 120 * 1000, + ); // 120 seconds should be enough to generate the proof with 16-bit range checks }); diff --git a/yarn-project/simulator/src/public/db.ts b/yarn-project/simulator/src/public/db.ts index 88d2a66025a..68e08315d6b 100644 --- a/yarn-project/simulator/src/public/db.ts +++ b/yarn-project/simulator/src/public/db.ts @@ -92,6 +92,12 @@ export interface CommitmentsDB { secret: Fr, ): Promise>; + /** + * @param leafIndex the leaf to look up + * @returns The l1 to l2 leaf value or undefined if not found. + */ + getL1ToL2LeafValue(leafIndex: bigint): Promise; + /** * Gets the index of a commitment in the note hash tree. * @param commitment - The commitment. diff --git a/yarn-project/simulator/src/public/execution.ts b/yarn-project/simulator/src/public/execution.ts index 74d33ec15c6..8b16f6c8e49 100644 --- a/yarn-project/simulator/src/public/execution.ts +++ b/yarn-project/simulator/src/public/execution.ts @@ -1,6 +1,5 @@ import { type SimulationError, type UnencryptedFunctionL2Logs } from '@aztec/circuit-types'; import { - type AztecAddress, type ContractStorageRead, type ContractStorageUpdateRequest, type Fr, @@ -44,9 +43,14 @@ export interface PublicExecutionResult { contractStorageUpdateRequests: ContractStorageUpdateRequest[]; /** The results of nested calls. */ nestedExecutions: this[]; + /** + * The hashed logs with side effect counter. + * Note: required as we don't track the counter anywhere else. + */ + unencryptedLogsHashes: SideEffect[]; /** * Unencrypted logs emitted during execution of this function call. - * Note: These are preimages to `unencryptedLogsHash`. + * Note: These are preimages to `unencryptedLogsHashes`. */ unencryptedLogs: UnencryptedFunctionL2Logs; /** @@ -85,10 +89,8 @@ export function isPublicExecutionResult( */ export function collectPublicDataReads(execResult: PublicExecutionResult): PublicDataRead[] { // HACK(#1622): part of temporary hack - may be able to remove this function after public state ordering is fixed - const contractAddress = execResult.execution.callContext.storageContractAddress; - const thisExecPublicDataReads = execResult.contractStorageReads.map(read => - contractStorageReadToPublicDataRead(read, contractAddress), + contractStorageReadToPublicDataRead(read), ); const unsorted = [ ...thisExecPublicDataReads, @@ -105,10 +107,8 @@ export function collectPublicDataReads(execResult: PublicExecutionResult): Publi */ export function collectPublicDataUpdateRequests(execResult: PublicExecutionResult): PublicDataUpdateRequest[] { // HACK(#1622): part of temporary hack - may be able to remove this function after public state ordering is fixed - const contractAddress = execResult.execution.callContext.storageContractAddress; - const thisExecPublicDataUpdateRequests = execResult.contractStorageUpdateRequests.map(update => - contractStorageUpdateRequestToPublicDataUpdateRequest(update, contractAddress), + contractStorageUpdateRequestToPublicDataUpdateRequest(update), ); const unsorted = [ ...thisExecPublicDataUpdateRequests, @@ -123,9 +123,9 @@ export function collectPublicDataUpdateRequests(execResult: PublicExecutionResul * @param contractAddress - the contract address of the read * @returns The public data read. */ -function contractStorageReadToPublicDataRead(read: ContractStorageRead, contractAddress: AztecAddress): PublicDataRead { +function contractStorageReadToPublicDataRead(read: ContractStorageRead): PublicDataRead { return new PublicDataRead( - computePublicDataTreeLeafSlot(contractAddress, read.storageSlot), + computePublicDataTreeLeafSlot(read.contractAddress!, read.storageSlot), computePublicDataTreeValue(read.currentValue), read.sideEffectCounter!, ); @@ -139,10 +139,9 @@ function contractStorageReadToPublicDataRead(read: ContractStorageRead, contract */ function contractStorageUpdateRequestToPublicDataUpdateRequest( update: ContractStorageUpdateRequest, - contractAddress: AztecAddress, ): PublicDataUpdateRequest { return new PublicDataUpdateRequest( - computePublicDataTreeLeafSlot(contractAddress, update.storageSlot), + computePublicDataTreeLeafSlot(update.contractAddress!, update.storageSlot), computePublicDataTreeValue(update.newValue), update.sideEffectCounter!, ); diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 0acbc9d8be0..412ea1b973b 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -148,6 +148,7 @@ async function executePublicFunctionAcvm( contractStorageReads: [], contractStorageUpdateRequests: [], nestedExecutions: [], + unencryptedLogsHashes: [], unencryptedLogs: UnencryptedFunctionL2Logs.empty(), reverted, revertReason, @@ -169,6 +170,7 @@ async function executePublicFunctionAcvm( newNullifiers: newNullifiersPadded, startSideEffectCounter, endSideEffectCounter, + unencryptedLogsHashes: unencryptedLogsHashesPadded, } = PublicCircuitPublicInputs.fromFields(returnWitness); const returnValues = await context.unpackReturns(returnsHash); @@ -177,6 +179,7 @@ async function executePublicFunctionAcvm( const newL2ToL1Messages = newL2ToL1Msgs.filter(v => !v.isEmpty()); const newNoteHashes = newNoteHashesPadded.filter(v => !v.isEmpty()); const newNullifiers = newNullifiersPadded.filter(v => !v.isEmpty()); + const unencryptedLogsHashes = unencryptedLogsHashesPadded.filter(v => !v.isEmpty()); const { contractStorageReads, contractStorageUpdateRequests } = context.getStorageActionData(); @@ -208,6 +211,7 @@ async function executePublicFunctionAcvm( contractStorageUpdateRequests, returnValues, nestedExecutions, + unencryptedLogsHashes, unencryptedLogs, reverted: false, revertReason: undefined, diff --git a/yarn-project/simulator/src/public/hints_builder.ts b/yarn-project/simulator/src/public/hints_builder.ts index b2a581d7696..5cc4988fd6f 100644 --- a/yarn-project/simulator/src/public/hints_builder.ts +++ b/yarn-project/simulator/src/public/hints_builder.ts @@ -1,65 +1,77 @@ import { MerkleTreeId } from '@aztec/circuit-types'; import { type Fr, - MAX_NEW_NULLIFIERS_PER_TX, + type MAX_NEW_NULLIFIERS_PER_TX, type MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, type MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, + type MAX_PUBLIC_DATA_HINTS, + type MAX_PUBLIC_DATA_READS_PER_TX, + type MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MembershipWitness, NULLIFIER_TREE_HEIGHT, PUBLIC_DATA_TREE_HEIGHT, + type PublicDataHint, type PublicDataRead, - PublicDataTreeLeafPreimage, + type PublicDataTreeLeafPreimage, + type PublicDataUpdateRequest, type ReadRequestContext, type SideEffectLinkedToNoteHash, buildNullifierNonExistentReadRequestHints, buildNullifierReadRequestHints, - mergeAccumulatedData, + buildPublicDataHints, + buildPublicDataReadRequestHints, } from '@aztec/circuits.js'; -import { makeTuple } from '@aztec/foundation/array'; import { type Tuple } from '@aztec/foundation/serialize'; -import { type MerkleTreeOperations } from '@aztec/world-state'; +import { type IndexedTreeId, type MerkleTreeOperations } from '@aztec/world-state'; export class HintsBuilder { constructor(private db: MerkleTreeOperations) {} getNullifierReadRequestHints( nullifierReadRequests: Tuple, - nullifiersNonRevertible: Tuple, - nullifiersRevertible: Tuple, + pendingNullifiers: Tuple, ) { - return buildNullifierReadRequestHints( - this, - nullifierReadRequests, - mergeAccumulatedData(MAX_NEW_NULLIFIERS_PER_TX, nullifiersNonRevertible, nullifiersRevertible), - ); + return buildNullifierReadRequestHints(this, nullifierReadRequests, pendingNullifiers); } getNullifierNonExistentReadRequestHints( nullifierNonExistentReadRequests: Tuple, - nullifiersNonRevertible: Tuple, - nullifiersRevertible: Tuple, + pendingNullifiers: Tuple, ) { - const pendingNullifiers = mergeAccumulatedData( - MAX_NEW_NULLIFIERS_PER_TX, - nullifiersNonRevertible, - nullifiersRevertible, - ); return buildNullifierNonExistentReadRequestHints(this, nullifierNonExistentReadRequests, pendingNullifiers); } + getPublicDataHints( + publicDataReads: Tuple, + publicDataUpdateRequests: Tuple, + ) { + return buildPublicDataHints(this, publicDataReads, publicDataUpdateRequests); + } + + getPublicDataReadRequestHints( + publicDataReads: Tuple, + publicDataUpdateRequests: Tuple, + publicDataHints: Tuple, + ) { + return buildPublicDataReadRequestHints(publicDataReads, publicDataUpdateRequests, publicDataHints); + } + async getNullifierMembershipWitness(nullifier: Fr) { const index = await this.db.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer()); if (index === undefined) { - return; + throw new Error(`Cannot find the leaf for nullifier ${nullifier.toBigInt()}.`); } - return this.getNullifierMembershipWitnessWithPreimage(index); + return this.getMembershipWitnessWithPreimage( + MerkleTreeId.NULLIFIER_TREE, + NULLIFIER_TREE_HEIGHT, + index, + ); } async getLowNullifierMembershipWitness(nullifier: Fr) { const res = await this.db.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt()); - if (res === undefined) { + if (!res) { throw new Error(`Cannot find the low leaf for nullifier ${nullifier.toBigInt()}.`); } @@ -68,52 +80,40 @@ export class HintsBuilder { throw new Error(`Nullifier ${nullifier.toBigInt()} already exists in the tree.`); } - return this.getNullifierMembershipWitnessWithPreimage(index); - } - - private async getNullifierMembershipWitnessWithPreimage(index: bigint) { - const siblingPath = await this.db.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, index); - const membershipWitness = new MembershipWitness( + return this.getMembershipWitnessWithPreimage( + MerkleTreeId.NULLIFIER_TREE, NULLIFIER_TREE_HEIGHT, index, - siblingPath.toTuple(), ); + } - const leafPreimage = await this.db.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index); - if (!leafPreimage) { - throw new Error(`Cannot find the leaf preimage at index ${index}.`); + async getMatchOrLowPublicDataMembershipWitness(leafSlot: bigint) { + const res = await this.db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot); + if (!res) { + throw new Error(`Cannot find the previous value index for public data ${leafSlot}.`); } - return { membershipWitness, leafPreimage }; + const { membershipWitness, leafPreimage } = await this.getMembershipWitnessWithPreimage< + typeof PUBLIC_DATA_TREE_HEIGHT + >(MerkleTreeId.PUBLIC_DATA_TREE, PUBLIC_DATA_TREE_HEIGHT, res.index); + + // Should find a way to stop casting IndexedTreeLeafPreimage as PublicDataTreeLeafPreimage everywhere. + return { membershipWitness, leafPreimage: leafPreimage as PublicDataTreeLeafPreimage }; } - async getPublicDataReadsInfo(publicDataReads: PublicDataRead[]) { - const newPublicDataReadsWitnesses: Tuple< - MembershipWitness, - typeof MAX_PUBLIC_DATA_READS_PER_TX - > = makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => MembershipWitness.empty(PUBLIC_DATA_TREE_HEIGHT, 0n)); - - const newPublicDataReadsPreimages: Tuple = - makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, () => PublicDataTreeLeafPreimage.empty()); - - for (const i in publicDataReads) { - const leafSlot = publicDataReads[i].leafSlot.value; - const lowLeafResult = await this.db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot); - if (!lowLeafResult) { - throw new Error(`Public data tree should have one initial leaf`); - } - const preimage = await this.db.getLeafPreimage(MerkleTreeId.PUBLIC_DATA_TREE, lowLeafResult.index); - const path = await this.db.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, lowLeafResult.index); - newPublicDataReadsWitnesses[i] = new MembershipWitness( - PUBLIC_DATA_TREE_HEIGHT, - BigInt(lowLeafResult.index), - path.toTuple(), - ); - newPublicDataReadsPreimages[i] = preimage! as PublicDataTreeLeafPreimage; + private async getMembershipWitnessWithPreimage( + treeId: IndexedTreeId, + treeHeight: TREE_HEIGHT, + index: bigint, + ) { + const siblingPath = await this.db.getSiblingPath(treeId, index); + const membershipWitness = new MembershipWitness(treeHeight, index, siblingPath.toTuple()); + + const leafPreimage = await this.db.getLeafPreimage(treeId, index); + if (!leafPreimage) { + throw new Error(`Cannot find the leaf preimage for tree ${treeId} at index ${index}.`); } - return { - newPublicDataReadsWitnesses, - newPublicDataReadsPreimages, - }; + + return { membershipWitness, leafPreimage }; } } diff --git a/yarn-project/simulator/src/public/index.test.ts b/yarn-project/simulator/src/public/index.test.ts index 5f97336dcbf..6f74908fadd 100644 --- a/yarn-project/simulator/src/public/index.test.ts +++ b/yarn-project/simulator/src/public/index.test.ts @@ -148,11 +148,13 @@ describe('ACIR public execution simulator', () => { // There should be 2 storage updates, one for the recipient's balance and one for the total supply expect(result.contractStorageUpdateRequests).toEqual([ { + contractAddress, storageSlot: recipientBalanceStorageSlot, newValue: expectedBalance, sideEffectCounter: 3, }, { + contractAddress, storageSlot: totalSupplyStorageSlot, newValue: expectedTotalSupply, sideEffectCounter: 4, @@ -165,6 +167,7 @@ describe('ACIR public execution simulator', () => { // the updates expect(result.contractStorageReads).toEqual([ { + contractAddress, storageSlot: isMinterStorageSlot, currentValue: isMinter, sideEffectCounter: 0, @@ -223,11 +226,13 @@ describe('ACIR public execution simulator', () => { expect(result.contractStorageUpdateRequests).toEqual([ { + contractAddress, storageSlot: senderStorageSlot, newValue: expectedSenderBalance, sideEffectCounter: 1, // 1 read (sender balance) }, { + contractAddress, storageSlot: recipientStorageSlot, newValue: expectedRecipientBalance, sideEffectCounter: 3, // 1 read (sender balance), 1 write (new sender balance), 1 read (recipient balance) @@ -392,6 +397,7 @@ describe('ACIR public execution simulator', () => { const tokenRecipient = AztecAddress.random(); let bridgedAmount = 20n; let secret = new Fr(1); + let leafIndex: bigint; let crossChainMsgRecipient: AztecAddress | undefined; let crossChainMsgSender: EthAddress | undefined; @@ -405,6 +411,7 @@ describe('ACIR public execution simulator', () => { beforeEach(() => { bridgedAmount = 20n; secret = new Fr(1); + leafIndex = 0n; crossChainMsgRecipient = undefined; crossChainMsgSender = undefined; @@ -418,7 +425,7 @@ describe('ACIR public execution simulator', () => { secret, ); - const computeArgs = () => encodeArguments(mintPublicArtifact, [tokenRecipient, bridgedAmount, secret]); + const computeArgs = () => encodeArguments(mintPublicArtifact, [tokenRecipient, bridgedAmount, secret, leafIndex]); const computeCallContext = () => makeCallContext(contractAddress, { @@ -450,7 +457,7 @@ describe('ACIR public execution simulator', () => { root = pedersenHash([root, sibling]); } commitmentsDb.getL1ToL2MembershipWitness.mockImplementation(() => { - return Promise.resolve(new MessageLoadOracleInputs(0n, siblingPath)); + return Promise.resolve(new MessageLoadOracleInputs(leafIndex, siblingPath)); }); if (updateState) { diff --git a/yarn-project/simulator/src/public/public_execution_context.ts b/yarn-project/simulator/src/public/public_execution_context.ts index e0b0922c934..ad2c77b0dc9 100644 --- a/yarn-project/simulator/src/public/public_execution_context.ts +++ b/yarn-project/simulator/src/public/public_execution_context.ts @@ -90,10 +90,10 @@ export class PublicExecutionContext extends TypedOracle { } /** - * Pack the given arguments. + * Pack the given array of arguments. * @param args - Arguments to pack */ - public override packArguments(args: Fr[]): Promise { + public override packArgumentsArray(args: Fr[]): Promise { return Promise.resolve(this.packedValuesCache.pack(args)); } @@ -133,6 +133,7 @@ export class PublicExecutionContext extends TypedOracle { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/885) this.unencryptedLogs.push(log); this.log.verbose(`Emitted unencrypted log: "${log.toHumanReadable()}"`); + return Fr.fromBuffer(log.hash()); } /** diff --git a/yarn-project/simulator/src/public/public_executor.ts b/yarn-project/simulator/src/public/public_executor.ts index 1f1bc28115e..c40a815732b 100644 --- a/yarn-project/simulator/src/public/public_executor.ts +++ b/yarn-project/simulator/src/public/public_executor.ts @@ -257,6 +257,10 @@ export class WorldStateDB implements CommitmentsDB { return new MessageLoadOracleInputs(messageIndex, siblingPath); } + public async getL1ToL2LeafValue(leafIndex: bigint): Promise { + return await this.db.getLeafValue(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, leafIndex); + } + public async getCommitmentIndex(commitment: Fr): Promise { return await this.db.findLeafIndex(MerkleTreeId.NOTE_HASH_TREE, commitment); } diff --git a/yarn-project/simulator/src/public/public_processor.test.ts b/yarn-project/simulator/src/public/public_processor.test.ts index 4d540b0a890..904321e2d6c 100644 --- a/yarn-project/simulator/src/public/public_processor.test.ts +++ b/yarn-project/simulator/src/public/public_processor.test.ts @@ -1,45 +1,39 @@ import { type BlockProver, - EncryptedTxL2Logs, type ProcessedTx, PublicDataWrite, - SiblingPath, SimulationError, - Tx, + type Tx, type TxValidator, - UnencryptedTxL2Logs, mockTx, toTxEffect, } from '@aztec/circuit-types'; import { + AppendOnlyTreeSnapshot, ContractStorageUpdateRequest, Fr, GlobalVariables, Header, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PUBLIC_DATA_TREE_HEIGHT, + PartialStateReference, type Proof, type PublicCallRequest, - PublicDataUpdateRequest, + PublicDataTreeLeafPreimage, + StateReference, makeEmptyProof, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; -import { - fr, - makeAztecAddress, - makePrivateKernelTailCircuitPublicInputs, - makePublicCallRequest, - makeSelector, -} from '@aztec/circuits.js/testing'; -import { makeTuple } from '@aztec/foundation/array'; -import { arrayNonEmptyLength, times } from '@aztec/foundation/collection'; +import { fr, makeAztecAddress, makePublicCallRequest, makeSelector } from '@aztec/circuits.js/testing'; +import { arrayNonEmptyLength } from '@aztec/foundation/collection'; +import { openTmpStore } from '@aztec/kv-store/utils'; +import { type AppendOnlyTree, Pedersen, StandardTree, newTree } from '@aztec/merkle-tree'; import { type PublicExecutionResult, type PublicExecutor, WASMSimulator } from '@aztec/simulator'; import { type MerkleTreeOperations, type TreeInfo } from '@aztec/world-state'; import { jest } from '@jest/globals'; import { type MockProxy, mock } from 'jest-mock-extended'; -import { PublicExecutionResultBuilder, addKernelPublicCallStack, makeFunctionCall } from '../mocks/fixtures.js'; +import { PublicExecutionResultBuilder, makeFunctionCall } from '../mocks/fixtures.js'; import { type ContractsDataSourcePublicDB, type WorldStatePublicDB } from './public_executor.js'; import { RealPublicKernelCircuitSimulator } from './public_kernel.js'; import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; @@ -143,17 +137,68 @@ describe('public_processor', () => { describe('with actual circuits', () => { let publicKernel: PublicKernelCircuitSimulator; + let publicDataTree: AppendOnlyTree; + + const mockTxWithPartialState = ( + { + hasLogs = false, + numberOfNonRevertiblePublicCallRequests = 0, + numberOfRevertiblePublicCallRequests = 0, + publicCallRequests = [], + }: { + hasLogs?: boolean; + numberOfNonRevertiblePublicCallRequests?: number; + numberOfRevertiblePublicCallRequests?: number; + publicCallRequests?: PublicCallRequest[]; + } = {}, + seed = 1, + ) => { + return mockTx(seed, { + hasLogs, + numberOfNonRevertiblePublicCallRequests, + numberOfRevertiblePublicCallRequests, + publicCallRequests, + }); + }; + + beforeAll(async () => { + publicDataTree = await newTree( + StandardTree, + openTmpStore(), + new Pedersen(), + 'PublicData', + Fr, + PUBLIC_DATA_TREE_HEIGHT, + 1, // Add a default low leaf for the public data hints to be proved against. + ); + }); beforeEach(() => { - const path = times(PUBLIC_DATA_TREE_HEIGHT, i => Buffer.alloc(32, i)); - db.getSiblingPath.mockResolvedValue(new SiblingPath(PUBLIC_DATA_TREE_HEIGHT, path)); + const snap = new AppendOnlyTreeSnapshot( + Fr.fromBuffer(publicDataTree.getRoot(true)), + Number(publicDataTree.getNumLeaves(true)), + ); + + const header = Header.empty(); + const stateReference = new StateReference( + header.state.l1ToL2MessageTree, + new PartialStateReference(header.state.partial.noteHashTree, header.state.partial.nullifierTree, snap), + ); + // Clone the whole state because somewhere down the line (AbstractPhaseManager) the public data root is modified in the referenced header directly :/ + header.state = StateReference.fromBuffer(stateReference.toBuffer()); + + db.getStateReference.mockResolvedValue(stateReference); + db.getSiblingPath.mockResolvedValue(publicDataTree.getSiblingPath(0n, false)); + db.getPreviousValueIndex.mockResolvedValue({ index: 0n, alreadyPresent: true }); + db.getLeafPreimage.mockResolvedValue(new PublicDataTreeLeafPreimage(new Fr(0), new Fr(0), new Fr(0), 0n)); + publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator()); processor = new PublicProcessor( db, publicExecutor, publicKernel, GlobalVariables.empty(), - Header.empty(), + header, publicContractsDB, publicWorldStateDB, ); @@ -166,7 +211,9 @@ describe('public_processor', () => { }); it('runs a tx with enqueued public calls', async function () { - const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 2 }); + const tx = mockTxWithPartialState({ + numberOfRevertiblePublicCallRequests: 2, + }); publicExecutor.simulate.mockImplementation(execution => { for (const request of tx.enqueuedPublicFunctionCalls) { @@ -192,7 +239,7 @@ describe('public_processor', () => { }); it('runs a tx with an enqueued public call with nested execution', async function () { - const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 1 }); + const tx = mockTxWithPartialState({ numberOfRevertiblePublicCallRequests: 1 }); const callRequest = tx.enqueuedPublicFunctionCalls[0]; const publicExecutionResult = PublicExecutionResultBuilder.fromPublicCallRequest({ @@ -223,7 +270,7 @@ describe('public_processor', () => { it('does not attempt to overfill a block', async function () { const txs = Array.from([1, 2, 3], index => - mockTx(index, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 1 }), + mockTxWithPartialState({ numberOfRevertiblePublicCallRequests: 1 }, index), ); let txCount = 0; @@ -255,7 +302,7 @@ describe('public_processor', () => { }); it('does not send a transaction to the prover if validation fails', async function () { - const tx = mockTx(1, { numberOfNonRevertiblePublicCallRequests: 0, numberOfRevertiblePublicCallRequests: 1 }); + const tx = mockTxWithPartialState({ numberOfRevertiblePublicCallRequests: 1 }); publicExecutor.simulate.mockImplementation(execution => { for (const request of tx.enqueuedPublicFunctionCalls) { @@ -283,40 +330,21 @@ describe('public_processor', () => { it('rolls back app logic db updates on failed public execution, but persists setup/teardown', async function () { const baseContractAddressSeed = 0x200; const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const callRequests: PublicCallRequest[] = [ + const publicCallRequests: PublicCallRequest[] = [ baseContractAddressSeed, baseContractAddressSeed, baseContractAddressSeed, ].map(makePublicCallRequest); - callRequests[0].callContext.sideEffectCounter = 2; - callRequests[1].callContext.sideEffectCounter = 3; - callRequests[2].callContext.sideEffectCounter = 4; - - const kernelOutput = makePrivateKernelTailCircuitPublicInputs(0x10); - kernelOutput.forPublic!.endNonRevertibleData.publicDataUpdateRequests = makeTuple( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - PublicDataUpdateRequest.empty, - ); - kernelOutput.forPublic!.end.publicDataUpdateRequests = makeTuple( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - PublicDataUpdateRequest.empty, - ); - - addKernelPublicCallStack(kernelOutput, { - setupCalls: [callRequests[0]], - appLogicCalls: [callRequests[2]], - teardownCall: callRequests[1], + publicCallRequests[0].callContext.sideEffectCounter = 2; + publicCallRequests[1].callContext.sideEffectCounter = 3; + publicCallRequests[2].callContext.sideEffectCounter = 4; + + const tx = mockTxWithPartialState({ + numberOfNonRevertiblePublicCallRequests: 2, + numberOfRevertiblePublicCallRequests: 1, + publicCallRequests, }); - const tx = new Tx( - kernelOutput, - proof, - EncryptedTxL2Logs.empty(), - UnencryptedTxL2Logs.empty(), - // reverse because `enqueuedPublicFunctions` expects the last element to be the front of the queue - callRequests.slice().reverse(), - ); - const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); const contractSlotC = fr(0x200); @@ -325,24 +353,26 @@ describe('public_processor', () => { const simulatorResults: PublicExecutionResult[] = [ // Setup PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[0], - contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotA, fr(0x101))], + request: publicCallRequests[0], + contractStorageUpdateRequests: [ + new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), + ], }).build(), // App Logic PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[2], + request: publicCallRequests[2], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102)), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151)), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 13, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 14, baseContractAddress), ], }).build(), PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), revertReason: new SimulationError('Simulation Failed', []), }).build(), @@ -351,12 +381,14 @@ describe('public_processor', () => { // Teardown PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[1], + request: publicCallRequests[1], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x201))], + contractStorageUpdateRequests: [ + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 12, baseContractAddress), + ], }).build(), ], }).build(), @@ -406,32 +438,21 @@ describe('public_processor', () => { it('fails a transaction that reverts in setup', async function () { const baseContractAddressSeed = 0x200; const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const callRequests: PublicCallRequest[] = [ + const publicCallRequests: PublicCallRequest[] = [ baseContractAddressSeed, baseContractAddressSeed, baseContractAddressSeed, ].map(makePublicCallRequest); - callRequests[0].callContext.sideEffectCounter = 2; - callRequests[1].callContext.sideEffectCounter = 3; - callRequests[2].callContext.sideEffectCounter = 4; - - const kernelOutput = makePrivateKernelTailCircuitPublicInputs(0x10); - - addKernelPublicCallStack(kernelOutput, { - setupCalls: [callRequests[0]], - appLogicCalls: [callRequests[2]], - teardownCall: callRequests[1], + publicCallRequests[0].callContext.sideEffectCounter = 2; + publicCallRequests[1].callContext.sideEffectCounter = 3; + publicCallRequests[2].callContext.sideEffectCounter = 4; + + const tx = mockTxWithPartialState({ + numberOfNonRevertiblePublicCallRequests: 2, + numberOfRevertiblePublicCallRequests: 1, + publicCallRequests, }); - const tx = new Tx( - kernelOutput, - proof, - EncryptedTxL2Logs.empty(), - UnencryptedTxL2Logs.empty(), - // reverse because `enqueuedPublicFunctions` expects the last element to be the front of the queue - callRequests.slice().reverse(), - ); - const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); const contractSlotC = fr(0x200); @@ -440,19 +461,21 @@ describe('public_processor', () => { const simulatorResults: PublicExecutionResult[] = [ // Setup PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[0], - contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotA, fr(0x101))], + request: publicCallRequests[0], + contractStorageUpdateRequests: [ + new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), + ], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102)), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151)), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13, baseContractAddress), ], }).build(), PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), revertReason: new SimulationError('Simulation Failed', []), }).build(), @@ -461,17 +484,19 @@ describe('public_processor', () => { // App Logic PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[2], + request: publicCallRequests[2], }).build(), // Teardown PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[1], + request: publicCallRequests[1], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x201))], + contractStorageUpdateRequests: [ + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 14, baseContractAddress), + ], }).build(), ], }).build(), @@ -511,32 +536,21 @@ describe('public_processor', () => { it('fails a transaction that reverts in teardown', async function () { const baseContractAddressSeed = 0x200; const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const callRequests: PublicCallRequest[] = [ + const publicCallRequests: PublicCallRequest[] = [ baseContractAddressSeed, baseContractAddressSeed, baseContractAddressSeed, ].map(makePublicCallRequest); - callRequests[0].callContext.sideEffectCounter = 2; - callRequests[1].callContext.sideEffectCounter = 3; - callRequests[2].callContext.sideEffectCounter = 4; - - const kernelOutput = makePrivateKernelTailCircuitPublicInputs(0x10); - - addKernelPublicCallStack(kernelOutput, { - setupCalls: [callRequests[0]], - appLogicCalls: [callRequests[2]], - teardownCall: callRequests[1], + publicCallRequests[0].callContext.sideEffectCounter = 2; + publicCallRequests[1].callContext.sideEffectCounter = 3; + publicCallRequests[2].callContext.sideEffectCounter = 4; + + const tx = mockTxWithPartialState({ + numberOfNonRevertiblePublicCallRequests: 2, + numberOfRevertiblePublicCallRequests: 1, + publicCallRequests, }); - const tx = new Tx( - kernelOutput, - proof, - EncryptedTxL2Logs.empty(), - UnencryptedTxL2Logs.empty(), - // reverse because `enqueuedPublicFunctions` expects the last element to be the front of the queue - callRequests.slice().reverse(), - ); - const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); const contractSlotC = fr(0x200); @@ -545,15 +559,17 @@ describe('public_processor', () => { const simulatorResults: PublicExecutionResult[] = [ // Setup PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[0], - contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotA, fr(0x101))], + request: publicCallRequests[0], + contractStorageUpdateRequests: [ + new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), + ], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x102)), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151)), + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 12, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 13, baseContractAddress), ], }).build(), ], @@ -561,22 +577,24 @@ describe('public_processor', () => { // App Logic PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[2], + request: publicCallRequests[2], }).build(), // Teardown PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[1], + request: publicCallRequests[1], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), revertReason: new SimulationError('Simulation Failed', []), }).build(), PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotC, fr(0x201))], + contractStorageUpdateRequests: [ + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 14, baseContractAddress), + ], }).build(), ], }).build(), @@ -615,42 +633,21 @@ describe('public_processor', () => { it('runs a tx with setup and teardown phases', async function () { const baseContractAddressSeed = 0x200; const baseContractAddress = makeAztecAddress(baseContractAddressSeed); - const callRequests: PublicCallRequest[] = [ + const publicCallRequests: PublicCallRequest[] = [ baseContractAddressSeed, baseContractAddressSeed, baseContractAddressSeed, ].map(makePublicCallRequest); - callRequests[0].callContext.sideEffectCounter = 2; - callRequests[1].callContext.sideEffectCounter = 3; - callRequests[2].callContext.sideEffectCounter = 4; - - const kernelOutput = makePrivateKernelTailCircuitPublicInputs(0x10); - kernelOutput.forPublic!.end.encryptedLogsHash = Fr.ZERO; - kernelOutput.forPublic!.end.unencryptedLogsHash = Fr.ZERO; - kernelOutput.forPublic!.endNonRevertibleData.publicDataUpdateRequests = makeTuple( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - PublicDataUpdateRequest.empty, - ); - kernelOutput.forPublic!.end.publicDataUpdateRequests = makeTuple( - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - PublicDataUpdateRequest.empty, - ); - - addKernelPublicCallStack(kernelOutput, { - setupCalls: [callRequests[0]], - appLogicCalls: [callRequests[2]], - teardownCall: callRequests[1], + publicCallRequests[0].callContext.sideEffectCounter = 2; + publicCallRequests[1].callContext.sideEffectCounter = 3; + publicCallRequests[2].callContext.sideEffectCounter = 4; + + const tx = mockTxWithPartialState({ + numberOfNonRevertiblePublicCallRequests: 2, + numberOfRevertiblePublicCallRequests: 1, + publicCallRequests, }); - const tx = new Tx( - kernelOutput, - proof, - EncryptedTxL2Logs.empty(), - UnencryptedTxL2Logs.empty(), - // reverse because `enqueuedPublicFunctions` expects the last element to be the front of the queue - callRequests.slice().reverse(), - ); - // const baseContractAddress = makeAztecAddress(30); const contractSlotA = fr(0x100); const contractSlotB = fr(0x150); @@ -659,33 +656,35 @@ describe('public_processor', () => { let simulatorCallCount = 0; const simulatorResults: PublicExecutionResult[] = [ // Setup - PublicExecutionResultBuilder.fromPublicCallRequest({ request: callRequests[0] }).build(), + PublicExecutionResultBuilder.fromPublicCallRequest({ request: publicCallRequests[0] }).build(), // App Logic PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[2], + request: publicCallRequests[2], contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x101)), - new ContractStorageUpdateRequest(contractSlotB, fr(0x151)), + new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 14, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotB, fr(0x151), 15, baseContractAddress), ], }).build(), // Teardown PublicExecutionResultBuilder.fromPublicCallRequest({ - request: callRequests[1], + request: publicCallRequests[1], nestedExecutions: [ PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), contractStorageUpdateRequests: [ - new ContractStorageUpdateRequest(contractSlotA, fr(0x101)), - new ContractStorageUpdateRequest(contractSlotC, fr(0x201)), + new ContractStorageUpdateRequest(contractSlotA, fr(0x101), 11, baseContractAddress), + new ContractStorageUpdateRequest(contractSlotC, fr(0x201), 12, baseContractAddress), ], }).build(), PublicExecutionResultBuilder.fromFunctionCall({ - from: callRequests[1].contractAddress, + from: publicCallRequests[1].contractAddress, tx: makeFunctionCall(baseContractAddress, makeSelector(5)), - contractStorageUpdateRequests: [new ContractStorageUpdateRequest(contractSlotA, fr(0x102))], + contractStorageUpdateRequests: [ + new ContractStorageUpdateRequest(contractSlotA, fr(0x102), 13, baseContractAddress), + ], }).build(), ], }).build(), diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 9354bd6d6e9..b749c2276fa 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -1,6 +1,7 @@ import { type BlockProver, type FailedTx, + type ProcessReturnValues, type ProcessedTx, type PublicKernelRequest, type SimulationError, @@ -13,7 +14,6 @@ import { } from '@aztec/circuit-types'; import { type TxSequencerProcessingStats } from '@aztec/circuit-types/stats'; import { type GlobalVariables, type Header, type KernelCircuitPublicInputs } from '@aztec/circuits.js'; -import { type ProcessReturnValues } from '@aztec/foundation/abi'; import { createDebugLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; import { PublicExecutor, type PublicStateDB, type SimulationProvider } from '@aztec/simulator'; diff --git a/yarn-project/simulator/src/public/state_actions.ts b/yarn-project/simulator/src/public/state_actions.ts index a4b63c54a60..cd25d82f669 100644 --- a/yarn-project/simulator/src/public/state_actions.ts +++ b/yarn-project/simulator/src/public/state_actions.ts @@ -83,6 +83,7 @@ export class ContractStorageActionsCollector { public collect(): [ContractStorageRead[], ContractStorageUpdateRequest[]] { const reads = Array.from(this.contractStorageReads.entries()).map(([slot, valueAndCounter]) => ContractStorageRead.from({ + contractAddress: this.address, storageSlot: new Fr(slot), ...valueAndCounter, }), @@ -90,6 +91,7 @@ export class ContractStorageActionsCollector { const updateRequests = Array.from(this.contractStorageUpdateRequests.entries()).map(([slot, valuesAndCounter]) => ContractStorageUpdateRequest.from({ + contractAddress: this.address, storageSlot: new Fr(slot), ...valuesAndCounter, }), diff --git a/yarn-project/simulator/src/public/tail_phase_manager.ts b/yarn-project/simulator/src/public/tail_phase_manager.ts index c1899ae2d72..c5c3487f1a9 100644 --- a/yarn-project/simulator/src/public/tail_phase_manager.ts +++ b/yarn-project/simulator/src/public/tail_phase_manager.ts @@ -1,14 +1,23 @@ -import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types'; import { - type Fr, + type PublicKernelRequest, + PublicKernelType, + type Tx, + UnencryptedFunctionL2Logs, + type UnencryptedL2Log, +} from '@aztec/circuit-types'; +import { + Fr, type GlobalVariables, type Header, type KernelCircuitPublicInputs, MAX_NEW_NOTE_HASHES_PER_TX, + MAX_NEW_NULLIFIERS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + type MAX_UNENCRYPTED_LOGS_PER_TX, type Proof, type PublicKernelCircuitPublicInputs, PublicKernelTailCircuitPrivateInputs, - type SideEffect, + SideEffect, makeEmptyProof, mergeAccumulatedData, sortByCounter, @@ -47,7 +56,8 @@ export class TailPhaseManager extends AbstractPhaseManager { throw err; }, ); - + // Temporary hack. Should sort them in the tail circuit. + this.patchLogsOrdering(tx, previousPublicKernelOutput); // commit the state updates from this transaction await this.publicStateDB.commit(); @@ -71,6 +81,10 @@ export class TailPhaseManager extends AbstractPhaseManager { previousOutput: PublicKernelCircuitPublicInputs, previousProof: Proof, ): Promise<[PublicKernelTailCircuitPrivateInputs, KernelCircuitPublicInputs]> { + // Temporary hack. Should sort them in the tail circuit. + previousOutput.end.unencryptedLogsHashes = this.sortLogsHashes( + previousOutput.end.unencryptedLogsHashes, + ); const [inputs, output] = await this.simulate(previousOutput, previousProof); // Temporary hack. Should sort them in the tail circuit. @@ -88,27 +102,59 @@ export class TailPhaseManager extends AbstractPhaseManager { previousOutput: PublicKernelCircuitPublicInputs, previousProof: Proof, ): Promise<[PublicKernelTailCircuitPrivateInputs, KernelCircuitPublicInputs]> { + const inputs = await this.buildPrivateInputs(previousOutput, previousProof); + // We take a deep copy (clone) of these to pass to the prover + return [inputs.clone(), await this.publicKernel.publicKernelCircuitTail(inputs)]; + } + + private async buildPrivateInputs(previousOutput: PublicKernelCircuitPublicInputs, previousProof: Proof) { const previousKernel = this.getPreviousKernelData(previousOutput, previousProof); const { validationRequests, endNonRevertibleData, end } = previousOutput; - const nullifierReadRequestHints = await this.hintsBuilder.getNullifierReadRequestHints( - validationRequests.nullifierReadRequests, + + const pendingNullifiers = mergeAccumulatedData( + MAX_NEW_NULLIFIERS_PER_TX, endNonRevertibleData.newNullifiers, end.newNullifiers, ); + + const nullifierReadRequestHints = await this.hintsBuilder.getNullifierReadRequestHints( + validationRequests.nullifierReadRequests, + pendingNullifiers, + ); + const nullifierNonExistentReadRequestHints = await this.hintsBuilder.getNullifierNonExistentReadRequestHints( validationRequests.nullifierNonExistentReadRequests, - endNonRevertibleData.newNullifiers, - end.newNullifiers, + pendingNullifiers, ); - // We take a deep copy (clone) of these to pass to the prover - const inputs = new PublicKernelTailCircuitPrivateInputs( + const pendingPublicDataWrites = mergeAccumulatedData( + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + endNonRevertibleData.publicDataUpdateRequests, + end.publicDataUpdateRequests, + ); + + const publicDataHints = await this.hintsBuilder.getPublicDataHints( + validationRequests.publicDataReads, + pendingPublicDataWrites, + ); + + const publicDataReadRequestHints = this.hintsBuilder.getPublicDataReadRequestHints( + validationRequests.publicDataReads, + pendingPublicDataWrites, + publicDataHints, + ); + + const currentState = await this.db.getStateReference(); + + return new PublicKernelTailCircuitPrivateInputs( previousKernel, nullifierReadRequestHints, nullifierNonExistentReadRequestHints, + publicDataHints, + publicDataReadRequestHints, + currentState.partial, ); - return [inputs.clone(), await this.publicKernel.publicKernelCircuitTail(inputs)]; } private sortNoteHashes(noteHashes: Tuple): Tuple { @@ -117,4 +163,35 @@ export class TailPhaseManager extends AbstractPhaseManager { N >; } + + private sortLogsHashes(unencryptedLogsHashes: Tuple): Tuple { + return sortByCounter(unencryptedLogsHashes.map(n => ({ ...n, counter: n.counter.toNumber() }))).map( + h => new SideEffect(h.value, new Fr(h.counter)), + ) as Tuple; + } + + // As above, this is a hack for unencrypted logs ordering, now they are sorted. Since the public kernel + // cannot keep track of side effects that happen after or before a nested call, we override the gathered logs. + // As a sanity check, we at least verify that the elements are the same, so we are only tweaking their ordering. + // See same fn in pxe_service.ts + // Added as part of resolving #5017 + private patchLogsOrdering(tx: Tx, publicInputs: PublicKernelCircuitPublicInputs) { + const unencLogs = tx.unencryptedLogs.unrollLogs(); + const sortedUnencLogs = publicInputs.end.unencryptedLogsHashes; + + const finalUnencLogs: UnencryptedL2Log[] = []; + sortedUnencLogs.forEach((sideEffect: SideEffect) => { + if (!sideEffect.isEmpty()) { + const isLog = (log: UnencryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value); + const thisLogIndex = unencLogs.findIndex(isLog); + finalUnencLogs.push(unencLogs[thisLogIndex]); + } + }); + const unencryptedLogs = new UnencryptedFunctionL2Logs(finalUnencLogs); + + tx.unencryptedLogs.functionLogs[0] = unencryptedLogs; + for (let i = 1; i < tx.unencryptedLogs.functionLogs.length; i++) { + tx.unencryptedLogs.functionLogs[i] = UnencryptedFunctionL2Logs.empty(); + } + } } diff --git a/yarn-project/simulator/src/public/transitional_adaptors.ts b/yarn-project/simulator/src/public/transitional_adaptors.ts index 81bd36011e6..81cd68ebab0 100644 --- a/yarn-project/simulator/src/public/transitional_adaptors.ts +++ b/yarn-project/simulator/src/public/transitional_adaptors.ts @@ -112,10 +112,10 @@ export async function convertAvmResults( const execution = executionContext.execution; const contractStorageReads: ContractStorageRead[] = newWorldState.storageReads.map( - read => new ContractStorageRead(read.slot, read.value, read.counter.toNumber()), + read => new ContractStorageRead(read.slot, read.value, read.counter.toNumber(), read.storageAddress), ); const contractStorageUpdateRequests: ContractStorageUpdateRequest[] = newWorldState.storageWrites.map( - write => new ContractStorageUpdateRequest(write.slot, write.value, write.counter.toNumber()), + write => new ContractStorageUpdateRequest(write.slot, write.value, write.counter.toNumber(), write.storageAddress), ); // We need to write the storage updates to the DB, because that's what the ACVM expects. // Assumes the updates are in the right order. @@ -143,6 +143,9 @@ export async function convertAvmResults( const unencryptedLogs: UnencryptedFunctionL2Logs = new UnencryptedFunctionL2Logs( newWorldState.newLogs.map(log => new UnencryptedL2Log(log.contractAddress, log.selector, log.data)), ); + const unencryptedLogsHashes = newWorldState.newLogsHashes.map( + logHash => new SideEffect(logHash.logHash, logHash.counter), + ); const newL2ToL1Messages = newWorldState.newL1Messages.map(m => new L2ToL1Message(m.recipient, m.content)); const returnValues = result.output; @@ -166,6 +169,7 @@ export async function convertAvmResults( contractStorageUpdateRequests, returnValues, nestedExecutions, + unencryptedLogsHashes, unencryptedLogs, reverted: result.reverted, revertReason: result.revertReason ? createSimulationError(result.revertReason) : undefined, diff --git a/yarn-project/simulator/src/public/utils.ts b/yarn-project/simulator/src/public/utils.ts index 8918c39030b..7a2fae3b78e 100644 --- a/yarn-project/simulator/src/public/utils.ts +++ b/yarn-project/simulator/src/public/utils.ts @@ -14,6 +14,7 @@ export function lastSideEffectCounter(tx: Tx): number { ...data.endNonRevertibleData.publicCallStack, ...data.end.newNoteHashes, ...data.end.newNullifiers, + ...data.end.unencryptedLogsHashes, ...data.end.publicCallStack, ]; diff --git a/yarn-project/tsconfig.json b/yarn-project/tsconfig.json index 95f7ccc5cee..eafb807f772 100644 --- a/yarn-project/tsconfig.json +++ b/yarn-project/tsconfig.json @@ -16,7 +16,7 @@ "resolveJsonModule": true, "composite": true, "skipLibCheck": true, - "noImplicitOverride": true, + "noImplicitOverride": true }, "references": [ { "path": "accounts/tsconfig.json" }, diff --git a/yarn-project/types/src/abi/contract_artifact.ts b/yarn-project/types/src/abi/contract_artifact.ts index b1b5ca3d8ac..f2c605a0886 100644 --- a/yarn-project/types/src/abi/contract_artifact.ts +++ b/yarn-project/types/src/abi/contract_artifact.ts @@ -117,9 +117,10 @@ type NoirCompiledContractFunction = NoirCompiledContract['functions'][number]; /** * Generates a function build artifact. Replaces verification key with a mock value. * @param fn - Noir function entry. + * @param contract - Parent contract. * @returns Function artifact. */ -function generateFunctionArtifact(fn: NoirCompiledContractFunction): FunctionArtifact { +function generateFunctionArtifact(fn: NoirCompiledContractFunction, contract: NoirCompiledContract): FunctionArtifact { if (fn.custom_attributes === undefined) { throw new Error( `No custom attributes found for contract function ${fn.name}. Try rebuilding the contract with the latest nargo version.`, @@ -134,10 +135,25 @@ function generateFunctionArtifact(fn: NoirCompiledContractFunction): FunctionArt parameters = parameters.slice(1); } - // If the function is secret, the return is the public inputs, which should be omitted let returnTypes: AbiType[] = []; - if (functionType !== 'secret' && fn.abi.return_type) { + if (functionType === FunctionType.UNCONSTRAINED && fn.abi.return_type) { returnTypes = [fn.abi.return_type.abi_type]; + } else { + const pathToFind = `${contract.name}::${fn.name}_abi`; + const abiStructs: AbiType[] = contract.outputs.structs['functions']; + + const returnStruct = abiStructs.find(a => a.kind === 'struct' && a.path === pathToFind); + + if (returnStruct) { + if (returnStruct.kind !== 'struct') { + throw new Error('Could not generate contract function artifact'); + } + + const returnTypeField = returnStruct.fields.find(field => field.name === 'return_type'); + if (returnTypeField) { + returnTypes = [returnTypeField.type]; + } + } } return { @@ -190,7 +206,7 @@ function hasKernelFunctionInputs(params: ABIParameter[]): boolean { function generateContractArtifact(contract: NoirCompiledContract, aztecNrVersion?: string): ContractArtifact { return { name: contract.name, - functions: contract.functions.map(generateFunctionArtifact), + functions: contract.functions.map(f => generateFunctionArtifact(f, contract)), outputs: contract.outputs, fileMap: contract.file_map, aztecNrVersion, diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 23adca3a1b6..1121959ee0b 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -103,7 +103,6 @@ __metadata: debug: ^4.3.4 jest: ^29.5.0 jest-mock-extended: ^3.0.4 - lmdb: ^2.9.2 lodash.groupby: ^4.6.0 lodash.omit: ^4.5.0 ts-node: ^10.9.1 @@ -556,7 +555,7 @@ __metadata: "@types/node": ^18.7.23 jest: ^29.5.0 jest-mock-extended: ^3.0.3 - lmdb: ^2.9.2 + lmdb: ^3.0.6 ts-node: ^10.9.1 typescript: ^5.0.4 languageName: unknown @@ -607,6 +606,7 @@ __metadata: "@types/jest": ^29.5.0 "@types/lodash.camelcase": ^4.3.7 "@types/lodash.capitalize": ^4.2.7 + "@types/lodash.uniqby": ^4.7.9 "@types/node": ^18.7.23 "@types/pako": ^2.0.0 "@types/semver": ^7.5.4 @@ -616,6 +616,7 @@ __metadata: jest: ^29.5.0 lodash.camelcase: ^4.3.0 lodash.capitalize: ^4.2.1 + lodash.uniqby: ^4.7.0 memfs: ^4.6.0 pako: ^2.1.0 semver: ^7.5.4 @@ -2563,44 +2564,44 @@ __metadata: languageName: node linkType: hard -"@lmdb/lmdb-darwin-arm64@npm:2.9.2": - version: 2.9.2 - resolution: "@lmdb/lmdb-darwin-arm64@npm:2.9.2" +"@lmdb/lmdb-darwin-arm64@npm:3.0.6": + version: 3.0.6 + resolution: "@lmdb/lmdb-darwin-arm64@npm:3.0.6" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@lmdb/lmdb-darwin-x64@npm:2.9.2": - version: 2.9.2 - resolution: "@lmdb/lmdb-darwin-x64@npm:2.9.2" +"@lmdb/lmdb-darwin-x64@npm:3.0.6": + version: 3.0.6 + resolution: "@lmdb/lmdb-darwin-x64@npm:3.0.6" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@lmdb/lmdb-linux-arm64@npm:2.9.2": - version: 2.9.2 - resolution: "@lmdb/lmdb-linux-arm64@npm:2.9.2" +"@lmdb/lmdb-linux-arm64@npm:3.0.6": + version: 3.0.6 + resolution: "@lmdb/lmdb-linux-arm64@npm:3.0.6" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@lmdb/lmdb-linux-arm@npm:2.9.2": - version: 2.9.2 - resolution: "@lmdb/lmdb-linux-arm@npm:2.9.2" +"@lmdb/lmdb-linux-arm@npm:3.0.6": + version: 3.0.6 + resolution: "@lmdb/lmdb-linux-arm@npm:3.0.6" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@lmdb/lmdb-linux-x64@npm:2.9.2": - version: 2.9.2 - resolution: "@lmdb/lmdb-linux-x64@npm:2.9.2" +"@lmdb/lmdb-linux-x64@npm:3.0.6": + version: 3.0.6 + resolution: "@lmdb/lmdb-linux-x64@npm:3.0.6" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@lmdb/lmdb-win32-x64@npm:2.9.2": - version: 2.9.2 - resolution: "@lmdb/lmdb-win32-x64@npm:2.9.2" +"@lmdb/lmdb-win32-x64@npm:3.0.6": + version: 3.0.6 + resolution: "@lmdb/lmdb-win32-x64@npm:3.0.6" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -3634,6 +3635,15 @@ __metadata: languageName: node linkType: hard +"@types/lodash.uniqby@npm:^4.7.9": + version: 4.7.9 + resolution: "@types/lodash.uniqby@npm:4.7.9" + dependencies: + "@types/lodash": "*" + checksum: 24cc8af36e0d4c52b7294c7ba7d814c89ce2c8118d94350bbed21031fef850fa1a280bfd2b30a47e0b5f7aa6ac649a36a5089aa76bc23787963a5ee6443f631e + languageName: node + linkType: hard + "@types/lodash@npm:*": version: 4.14.202 resolution: "@types/lodash@npm:4.14.202" @@ -9674,16 +9684,16 @@ __metadata: languageName: node linkType: hard -"lmdb@npm:^2.9.2": - version: 2.9.2 - resolution: "lmdb@npm:2.9.2" - dependencies: - "@lmdb/lmdb-darwin-arm64": 2.9.2 - "@lmdb/lmdb-darwin-x64": 2.9.2 - "@lmdb/lmdb-linux-arm": 2.9.2 - "@lmdb/lmdb-linux-arm64": 2.9.2 - "@lmdb/lmdb-linux-x64": 2.9.2 - "@lmdb/lmdb-win32-x64": 2.9.2 +"lmdb@npm:^3.0.6": + version: 3.0.6 + resolution: "lmdb@npm:3.0.6" + dependencies: + "@lmdb/lmdb-darwin-arm64": 3.0.6 + "@lmdb/lmdb-darwin-x64": 3.0.6 + "@lmdb/lmdb-linux-arm": 3.0.6 + "@lmdb/lmdb-linux-arm64": 3.0.6 + "@lmdb/lmdb-linux-x64": 3.0.6 + "@lmdb/lmdb-win32-x64": 3.0.6 msgpackr: ^1.9.9 node-addon-api: ^6.1.0 node-gyp: latest @@ -9705,7 +9715,7 @@ __metadata: optional: true bin: download-lmdb-prebuilds: bin/download-prebuilds.js - checksum: b2471c4d2c36f15a27233ae1eece86fcbb40613574ec54245cf697b16b1b35c70c72e4092dc739407df145f14b7c1b6b56c4281a439c314e79a5338df8b2b63b + checksum: e8ab5bbef94e254ec1fa85deec251c4b34047786c87f54abd842cd12c3f29d55f62828512a4b69046075a624a25b2327e232072be702a68fcb3d8183e0175cca languageName: node linkType: hard @@ -9844,6 +9854,13 @@ __metadata: languageName: node linkType: hard +"lodash.uniqby@npm:^4.7.0": + version: 4.7.0 + resolution: "lodash.uniqby@npm:4.7.0" + checksum: 659264545a95726d1493123345aad8cbf56e17810fa9a0b029852c6d42bc80517696af09d99b23bef1845d10d95e01b8b4a1da578f22aeba7a30d3e0022a4938 + languageName: node + linkType: hard + "lodash@npm:^4.17.21, lodash@npm:^4.17.4": version: 4.17.21 resolution: "lodash@npm:4.17.21"